ccxt 4.2.11 → 4.2.12
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/README.md +5 -5
- package/build.sh +2 -2
- package/dist/ccxt.browser.js +640 -261
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/_virtual/agent.js +7 -0
- package/dist/cjs/_virtual/parse-proxy-response.js +7 -0
- package/dist/cjs/_virtual/promisify.js +7 -0
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/js/ccxt.js +474 -0
- package/dist/cjs/js/src/abstract/ace.js +9 -0
- package/dist/cjs/js/src/abstract/alpaca.js +9 -0
- package/dist/cjs/js/src/abstract/ascendex.js +9 -0
- package/dist/cjs/js/src/abstract/bigone.js +9 -0
- package/dist/cjs/js/src/abstract/binance.js +9 -0
- package/dist/cjs/js/src/abstract/bingx.js +9 -0
- package/dist/cjs/js/src/abstract/bit2c.js +9 -0
- package/dist/cjs/js/src/abstract/bitbank.js +9 -0
- package/dist/cjs/js/src/abstract/bitbns.js +9 -0
- package/dist/cjs/js/src/abstract/bitfinex.js +9 -0
- package/dist/cjs/js/src/abstract/bitfinex2.js +9 -0
- package/dist/cjs/js/src/abstract/bitflyer.js +9 -0
- package/dist/cjs/js/src/abstract/bitforex.js +9 -0
- package/dist/cjs/js/src/abstract/bitget.js +9 -0
- package/dist/cjs/js/src/abstract/bithumb.js +9 -0
- package/dist/cjs/js/src/abstract/bitmart.js +9 -0
- package/dist/cjs/js/src/abstract/bitmex.js +9 -0
- package/dist/cjs/js/src/abstract/bitopro.js +9 -0
- package/dist/cjs/js/src/abstract/bitpanda.js +9 -0
- package/dist/cjs/js/src/abstract/bitrue.js +9 -0
- package/dist/cjs/js/src/abstract/bitso.js +9 -0
- package/dist/cjs/js/src/abstract/bitstamp.js +9 -0
- package/dist/cjs/js/src/abstract/bitteam.js +9 -0
- package/dist/cjs/js/src/abstract/bitvavo.js +9 -0
- package/dist/cjs/js/src/abstract/bl3p.js +9 -0
- package/dist/cjs/js/src/abstract/blockchaincom.js +9 -0
- package/dist/cjs/js/src/abstract/btcalpha.js +9 -0
- package/dist/cjs/js/src/abstract/btcbox.js +9 -0
- package/dist/cjs/js/src/abstract/btcmarkets.js +9 -0
- package/dist/cjs/js/src/abstract/btcturk.js +9 -0
- package/dist/cjs/js/src/abstract/bybit.js +9 -0
- package/dist/cjs/js/src/abstract/cex.js +9 -0
- package/dist/cjs/js/src/abstract/coinbase.js +9 -0
- package/dist/cjs/js/src/abstract/coinbasepro.js +9 -0
- package/dist/cjs/js/src/abstract/coincheck.js +9 -0
- package/dist/cjs/js/src/abstract/coinex.js +9 -0
- package/dist/cjs/js/src/abstract/coinlist.js +9 -0
- package/dist/cjs/js/src/abstract/coinmate.js +9 -0
- package/dist/cjs/js/src/abstract/coinone.js +9 -0
- package/dist/cjs/js/src/abstract/coinsph.js +9 -0
- package/dist/cjs/js/src/abstract/coinspot.js +9 -0
- package/dist/cjs/js/src/abstract/cryptocom.js +9 -0
- package/dist/cjs/js/src/abstract/currencycom.js +9 -0
- package/dist/cjs/js/src/abstract/delta.js +9 -0
- package/dist/cjs/js/src/abstract/deribit.js +9 -0
- package/dist/cjs/js/src/abstract/digifinex.js +9 -0
- package/dist/cjs/js/src/abstract/exmo.js +9 -0
- package/dist/cjs/js/src/abstract/gate.js +9 -0
- package/dist/cjs/js/src/abstract/gemini.js +9 -0
- package/dist/cjs/js/src/abstract/hitbtc.js +9 -0
- package/dist/cjs/js/src/abstract/hollaex.js +9 -0
- package/dist/cjs/js/src/abstract/htx.js +9 -0
- package/dist/cjs/js/src/abstract/huobijp.js +9 -0
- package/dist/cjs/js/src/abstract/idex.js +9 -0
- package/dist/cjs/js/src/abstract/independentreserve.js +9 -0
- package/dist/cjs/js/src/abstract/indodax.js +9 -0
- package/dist/cjs/js/src/abstract/kraken.js +9 -0
- package/dist/cjs/js/src/abstract/krakenfutures.js +9 -0
- package/dist/cjs/js/src/abstract/kucoin.js +9 -0
- package/dist/cjs/js/src/abstract/kucoinfutures.js +9 -0
- package/dist/cjs/js/src/abstract/kuna.js +9 -0
- package/dist/cjs/js/src/abstract/latoken.js +9 -0
- package/dist/cjs/js/src/abstract/lbank.js +9 -0
- package/dist/cjs/js/src/abstract/luno.js +9 -0
- package/dist/cjs/js/src/abstract/lykke.js +9 -0
- package/dist/cjs/js/src/abstract/mercado.js +9 -0
- package/dist/cjs/js/src/abstract/mexc.js +9 -0
- package/dist/cjs/js/src/abstract/ndax.js +9 -0
- package/dist/cjs/js/src/abstract/novadax.js +9 -0
- package/dist/cjs/js/src/abstract/oceanex.js +9 -0
- package/dist/cjs/js/src/abstract/okcoin.js +9 -0
- package/dist/cjs/js/src/abstract/okx.js +9 -0
- package/dist/cjs/js/src/abstract/p2b.js +9 -0
- package/dist/cjs/js/src/abstract/paymium.js +9 -0
- package/dist/cjs/js/src/abstract/phemex.js +9 -0
- package/dist/cjs/js/src/abstract/poloniex.js +9 -0
- package/dist/cjs/js/src/abstract/poloniexfutures.js +9 -0
- package/dist/cjs/js/src/abstract/probit.js +9 -0
- package/dist/cjs/js/src/abstract/timex.js +9 -0
- package/dist/cjs/js/src/abstract/tokocrypto.js +9 -0
- package/dist/cjs/js/src/abstract/upbit.js +9 -0
- package/dist/cjs/js/src/abstract/wavesexchange.js +9 -0
- package/dist/cjs/js/src/abstract/wazirx.js +9 -0
- package/dist/cjs/js/src/abstract/whitebit.js +9 -0
- package/dist/cjs/js/src/abstract/woo.js +9 -0
- package/dist/cjs/js/src/abstract/yobit.js +9 -0
- package/dist/cjs/js/src/abstract/zaif.js +9 -0
- package/dist/cjs/js/src/abstract/zonda.js +9 -0
- package/dist/cjs/js/src/ace.js +1058 -0
- package/dist/cjs/js/src/alpaca.js +1125 -0
- package/dist/cjs/js/src/ascendex.js +3360 -0
- package/dist/cjs/js/src/base/Exchange.js +5110 -0
- package/dist/cjs/js/src/base/Precise.js +263 -0
- package/dist/cjs/js/src/base/errors.js +299 -0
- package/dist/cjs/js/src/base/functions/crypto.js +78 -0
- package/dist/cjs/js/src/base/functions/encode.js +44 -0
- package/dist/cjs/js/src/base/functions/generic.js +193 -0
- package/dist/cjs/js/src/base/functions/misc.js +96 -0
- package/dist/cjs/js/src/base/functions/number.js +297 -0
- package/dist/cjs/js/src/base/functions/platform.js +28 -0
- package/dist/cjs/js/src/base/functions/rsa.js +34 -0
- package/dist/cjs/js/src/base/functions/string.js +48 -0
- package/dist/cjs/js/src/base/functions/throttle.js +66 -0
- package/dist/cjs/js/src/base/functions/time.js +187 -0
- package/dist/cjs/js/src/base/functions/totp.js +24 -0
- package/dist/cjs/js/src/base/functions/type.js +162 -0
- package/dist/cjs/js/src/base/functions.js +157 -0
- package/dist/cjs/js/src/base/ws/Cache.js +254 -0
- package/dist/cjs/js/src/base/ws/Client.js +299 -0
- package/dist/cjs/js/src/base/ws/Future.js +34 -0
- package/dist/cjs/js/src/base/ws/OrderBook.js +107 -0
- package/dist/cjs/js/src/base/ws/OrderBookSide.js +281 -0
- package/dist/cjs/js/src/base/ws/WsClient.js +69 -0
- package/dist/cjs/js/src/bequant.js +33 -0
- package/dist/cjs/js/src/bigone.js +2142 -0
- package/dist/cjs/js/src/binance.js +9729 -0
- package/dist/cjs/js/src/binancecoinm.js +45 -0
- package/dist/cjs/js/src/binanceus.js +84 -0
- package/dist/cjs/js/src/binanceusdm.js +58 -0
- package/dist/cjs/js/src/bingx.js +3737 -0
- package/dist/cjs/js/src/bit2c.js +916 -0
- package/dist/cjs/js/src/bitbank.js +1000 -0
- package/dist/cjs/js/src/bitbay.js +17 -0
- package/dist/cjs/js/src/bitbns.js +1220 -0
- package/dist/cjs/js/src/bitcoincom.js +17 -0
- package/dist/cjs/js/src/bitfinex.js +1670 -0
- package/dist/cjs/js/src/bitfinex2.js +2990 -0
- package/dist/cjs/js/src/bitflyer.js +1045 -0
- package/dist/cjs/js/src/bitforex.js +852 -0
- package/dist/cjs/js/src/bitget.js +8284 -0
- package/dist/cjs/js/src/bithumb.js +1090 -0
- package/dist/cjs/js/src/bitmart.js +4454 -0
- package/dist/cjs/js/src/bitmex.js +2884 -0
- package/dist/cjs/js/src/bitopro.js +1724 -0
- package/dist/cjs/js/src/bitpanda.js +2002 -0
- package/dist/cjs/js/src/bitrue.js +3253 -0
- package/dist/cjs/js/src/bitso.js +1753 -0
- package/dist/cjs/js/src/bitstamp.js +2188 -0
- package/dist/cjs/js/src/bitteam.js +2309 -0
- package/dist/cjs/js/src/bitvavo.js +1968 -0
- package/dist/cjs/js/src/bl3p.js +447 -0
- package/dist/cjs/js/src/blockchaincom.js +1160 -0
- package/dist/cjs/js/src/btcalpha.js +929 -0
- package/dist/cjs/js/src/btcbox.js +565 -0
- package/dist/cjs/js/src/btcmarkets.js +1237 -0
- package/dist/cjs/js/src/btcturk.js +929 -0
- package/dist/cjs/js/src/bybit.js +7646 -0
- package/dist/cjs/js/src/cex.js +1693 -0
- package/dist/cjs/js/src/coinbase.js +3274 -0
- package/dist/cjs/js/src/coinbasepro.js +1866 -0
- package/dist/cjs/js/src/coincheck.js +843 -0
- package/dist/cjs/js/src/coinex.js +5414 -0
- package/dist/cjs/js/src/coinlist.js +2329 -0
- package/dist/cjs/js/src/coinmate.js +989 -0
- package/dist/cjs/js/src/coinone.js +1185 -0
- package/dist/cjs/js/src/coinsph.js +1933 -0
- package/dist/cjs/js/src/coinspot.js +548 -0
- package/dist/cjs/js/src/cryptocom.js +3007 -0
- package/dist/cjs/js/src/currencycom.js +2015 -0
- package/dist/cjs/js/src/delta.js +3256 -0
- package/dist/cjs/js/src/deribit.js +3306 -0
- package/dist/cjs/js/src/digifinex.js +4307 -0
- package/dist/cjs/js/src/exmo.js +2645 -0
- package/dist/cjs/js/src/fmfwio.js +34 -0
- package/dist/cjs/js/src/gate.js +7054 -0
- package/dist/cjs/js/src/gateio.js +16 -0
- package/dist/cjs/js/src/gemini.js +1801 -0
- package/dist/cjs/js/src/hitbtc.js +3660 -0
- package/dist/cjs/js/src/hitbtc3.js +19 -0
- package/dist/cjs/js/src/hollaex.js +1882 -0
- package/dist/cjs/js/src/htx.js +9024 -0
- package/dist/cjs/js/src/huobi.js +16 -0
- package/dist/cjs/js/src/huobijp.js +1918 -0
- package/dist/cjs/js/src/idex.js +1770 -0
- package/dist/cjs/js/src/independentreserve.js +759 -0
- package/dist/cjs/js/src/indodax.js +1069 -0
- package/dist/cjs/js/src/kraken.js +2861 -0
- package/dist/cjs/js/src/krakenfutures.js +2407 -0
- package/dist/cjs/js/src/kucoin.js +4489 -0
- package/dist/cjs/js/src/kucoinfutures.js +2475 -0
- package/dist/cjs/js/src/kuna.js +1949 -0
- package/dist/cjs/js/src/latoken.js +1729 -0
- package/dist/cjs/js/src/lbank.js +2825 -0
- package/dist/cjs/js/src/luno.js +1044 -0
- package/dist/cjs/js/src/lykke.js +1303 -0
- package/dist/cjs/js/src/mercado.js +897 -0
- package/dist/cjs/js/src/mexc.js +5407 -0
- package/dist/cjs/js/src/ndax.js +2450 -0
- package/dist/cjs/js/src/novadax.js +1556 -0
- package/dist/cjs/js/src/oceanex.js +964 -0
- package/dist/cjs/js/src/okcoin.js +3115 -0
- package/dist/cjs/js/src/okx.js +7329 -0
- package/dist/cjs/js/src/p2b.js +1243 -0
- package/dist/cjs/js/src/paymium.js +597 -0
- package/dist/cjs/js/src/phemex.js +4715 -0
- package/dist/cjs/js/src/poloniex.js +2356 -0
- package/dist/cjs/js/src/poloniexfutures.js +1794 -0
- package/dist/cjs/js/src/pro/alpaca.js +714 -0
- package/dist/cjs/js/src/pro/ascendex.js +957 -0
- package/dist/cjs/js/src/pro/bequant.js +33 -0
- package/dist/cjs/js/src/pro/binance.js +2796 -0
- package/dist/cjs/js/src/pro/binancecoinm.js +23 -0
- package/dist/cjs/js/src/pro/binanceus.js +51 -0
- package/dist/cjs/js/src/pro/binanceusdm.js +32 -0
- package/dist/cjs/js/src/pro/bingx.js +944 -0
- package/dist/cjs/js/src/pro/bitcoincom.js +29 -0
- package/dist/cjs/js/src/pro/bitfinex.js +672 -0
- package/dist/cjs/js/src/pro/bitfinex2.js +1159 -0
- package/dist/cjs/js/src/pro/bitget.js +1733 -0
- package/dist/cjs/js/src/pro/bitmart.js +1486 -0
- package/dist/cjs/js/src/pro/bitmex.js +1576 -0
- package/dist/cjs/js/src/pro/bitopro.js +327 -0
- package/dist/cjs/js/src/pro/bitpanda.js +1341 -0
- package/dist/cjs/js/src/pro/bitrue.js +462 -0
- package/dist/cjs/js/src/pro/bitstamp.js +547 -0
- package/dist/cjs/js/src/pro/bitvavo.js +704 -0
- package/dist/cjs/js/src/pro/blockchaincom.js +794 -0
- package/dist/cjs/js/src/pro/bybit.js +1843 -0
- package/dist/cjs/js/src/pro/cex.js +1510 -0
- package/dist/cjs/js/src/pro/coinbase.js +561 -0
- package/dist/cjs/js/src/pro/coinbasepro.js +968 -0
- package/dist/cjs/js/src/pro/coinex.js +1095 -0
- package/dist/cjs/js/src/pro/cryptocom.js +1020 -0
- package/dist/cjs/js/src/pro/currencycom.js +563 -0
- package/dist/cjs/js/src/pro/deribit.js +825 -0
- package/dist/cjs/js/src/pro/exmo.js +658 -0
- package/dist/cjs/js/src/pro/gate.js +1316 -0
- package/dist/cjs/js/src/pro/gateio.js +16 -0
- package/dist/cjs/js/src/pro/gemini.js +649 -0
- package/dist/cjs/js/src/pro/hitbtc.js +1293 -0
- package/dist/cjs/js/src/pro/hollaex.js +597 -0
- package/dist/cjs/js/src/pro/htx.js +2383 -0
- package/dist/cjs/js/src/pro/huobi.js +16 -0
- package/dist/cjs/js/src/pro/huobijp.js +606 -0
- package/dist/cjs/js/src/pro/idex.js +714 -0
- package/dist/cjs/js/src/pro/independentreserve.js +280 -0
- package/dist/cjs/js/src/pro/kraken.js +1364 -0
- package/dist/cjs/js/src/pro/krakenfutures.js +1500 -0
- package/dist/cjs/js/src/pro/kucoin.js +1052 -0
- package/dist/cjs/js/src/pro/kucoinfutures.js +981 -0
- package/dist/cjs/js/src/pro/luno.js +322 -0
- package/dist/cjs/js/src/pro/mexc.js +1170 -0
- package/dist/cjs/js/src/pro/ndax.js +545 -0
- package/dist/cjs/js/src/pro/okcoin.js +760 -0
- package/dist/cjs/js/src/pro/okx.js +1558 -0
- package/dist/cjs/js/src/pro/phemex.js +1511 -0
- package/dist/cjs/js/src/pro/poloniex.js +1253 -0
- package/dist/cjs/js/src/pro/poloniexfutures.js +1014 -0
- package/dist/cjs/js/src/pro/probit.js +586 -0
- package/dist/cjs/js/src/pro/upbit.js +234 -0
- package/dist/cjs/js/src/pro/wazirx.js +776 -0
- package/dist/cjs/js/src/pro/whitebit.js +927 -0
- package/dist/cjs/js/src/pro/woo.js +769 -0
- package/dist/cjs/js/src/probit.js +1865 -0
- package/dist/cjs/js/src/static_dependencies/fflake/browser.js +401 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/JSEncrypt.js +195 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/JSEncryptRSAKey.js +308 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/asn1.js +554 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/base64.js +94 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/hex.js +70 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/asn1js/int10.js +91 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/base64.js +16 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/jsbn.js +1760 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/prng4.js +52 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/rng.js +81 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/rsa.js +376 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsbn/util.js +70 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsrsasign/asn1-1.0.js +1580 -0
- package/dist/cjs/js/src/static_dependencies/jsencrypt/lib/jsrsasign/yahoo.js +74 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/_shortw_utils.js +24 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/curve.js +158 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/edwards.js +429 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/hash-to-curve.js +176 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/modular.js +324 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/montgomery.js +163 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/utils.js +245 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/abstract/weierstrass.js +1018 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/ed25519.js +383 -0
- package/dist/cjs/js/src/static_dependencies/noble-curves/secp256k1.js +258 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/_assert.js +53 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/_sha2.js +120 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/_u64.js +69 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/crypto.js +7 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/hmac.js +83 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/md5.js +240 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/sha1.js +91 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/sha256.js +130 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/sha3.js +214 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/sha512.js +239 -0
- package/dist/cjs/js/src/static_dependencies/noble-hashes/utils.js +93 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/body.js +354 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/errors/abort-error.js +16 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/errors/base.js +20 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/errors/fetch-error.js +30 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/headers.js +239 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/index.js +372 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/request.js +273 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/response.js +139 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/utils/get-search.js +14 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/utils/is-redirect.js +16 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/utils/is.js +81 -0
- package/dist/cjs/js/src/static_dependencies/node-fetch/utils/referrer.js +292 -0
- package/dist/cjs/js/src/static_dependencies/proxies/agent-base/index.js +103 -0
- package/dist/cjs/js/src/static_dependencies/proxies/http-proxy-agent/index.js +140 -0
- package/dist/cjs/js/src/static_dependencies/proxies/https-proxy-agent/index.js +175 -0
- package/dist/cjs/js/src/static_dependencies/proxies/https-proxy-agent/parse-proxy-response.js +95 -0
- package/dist/cjs/js/src/static_dependencies/qs/index.cjs.js +7 -0
- package/dist/cjs/js/src/static_dependencies/scure-base/index.js +383 -0
- package/dist/cjs/js/src/timex.js +1562 -0
- package/dist/cjs/js/src/tokocrypto.js +2542 -0
- package/dist/cjs/js/src/upbit.js +1844 -0
- package/dist/cjs/js/src/wavesexchange.js +2607 -0
- package/dist/cjs/js/src/wazirx.js +953 -0
- package/dist/cjs/js/src/whitebit.js +2309 -0
- package/dist/cjs/js/src/woo.js +2715 -0
- package/dist/cjs/js/src/yobit.js +1314 -0
- package/dist/cjs/js/src/zaif.js +736 -0
- package/dist/cjs/js/src/zonda.js +1883 -0
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/abstract/bigone.d.ts +18 -0
- package/js/src/abstract/binance.d.ts +2 -0
- package/js/src/abstract/binancecoinm.d.ts +2 -0
- package/js/src/abstract/binanceus.d.ts +2 -0
- package/js/src/abstract/binanceusdm.d.ts +2 -0
- package/js/src/abstract/bybit.d.ts +1 -0
- package/js/src/abstract/gate.d.ts +11 -0
- package/js/src/abstract/gateio.d.ts +11 -0
- package/js/src/alpaca.js +18 -18
- package/js/src/base/Exchange.d.ts +5 -1
- package/js/src/base/Exchange.js +101 -12
- package/js/src/bigone.d.ts +1 -2
- package/js/src/bigone.js +340 -145
- package/js/src/binance.js +15 -8
- package/js/src/bingx.js +9 -2
- package/js/src/bitfinex.d.ts +2 -2
- package/js/src/bitfinex.js +2 -3
- package/js/src/bitget.js +21 -8
- package/js/src/bitmart.d.ts +2 -2
- package/js/src/bitmart.js +3 -3
- package/js/src/bitmex.js +1 -0
- package/js/src/bybit.js +2 -0
- package/js/src/coinlist.js +2 -3
- package/js/src/coinsph.js +2 -3
- package/js/src/deribit.js +1 -0
- package/js/src/gate.d.ts +4 -4
- package/js/src/gate.js +22 -3
- package/js/src/hitbtc.d.ts +4 -4
- package/js/src/hitbtc.js +2 -3
- package/js/src/htx.js +4 -7
- package/js/src/huobijp.js +2 -3
- package/js/src/kraken.js +1 -0
- package/js/src/mexc.js +2 -1
- package/js/src/okx.js +13 -3
- package/js/src/pro/binance.d.ts +2 -23
- package/js/src/pro/binance.js +58 -22
- package/js/src/pro/coinbase.d.ts +2 -2
- package/js/src/pro/coinbase.js +4 -1
- package/js/src/pro/coinbasepro.d.ts +2 -2
- package/js/src/pro/hitbtc.d.ts +2 -2
- package/js/src/pro/poloniex.d.ts +2 -2
- package/js/src/upbit.d.ts +3 -101
- package/js/src/upbit.js +12 -12
- package/js/src/woo.js +2 -0
- package/package.json +1 -1
- package/skip-tests.json +5 -0
|
@@ -0,0 +1,2861 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var kraken$1 = require('./abstract/kraken.js');
|
|
4
|
+
var errors = require('./base/errors.js');
|
|
5
|
+
var Precise = require('./base/Precise.js');
|
|
6
|
+
var number = require('./base/functions/number.js');
|
|
7
|
+
var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
|
|
8
|
+
var sha512 = require('./static_dependencies/noble-hashes/sha512.js');
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* @class kraken
|
|
14
|
+
* @augments Exchange
|
|
15
|
+
*/
|
|
16
|
+
class kraken extends kraken$1 {
|
|
17
|
+
describe() {
|
|
18
|
+
return this.deepExtend(super.describe(), {
|
|
19
|
+
'id': 'kraken',
|
|
20
|
+
'name': 'Kraken',
|
|
21
|
+
'countries': ['US'],
|
|
22
|
+
'version': '0',
|
|
23
|
+
'rateLimit': 1000,
|
|
24
|
+
'certified': false,
|
|
25
|
+
'pro': true,
|
|
26
|
+
'has': {
|
|
27
|
+
'CORS': undefined,
|
|
28
|
+
'spot': true,
|
|
29
|
+
'margin': true,
|
|
30
|
+
'swap': false,
|
|
31
|
+
'future': false,
|
|
32
|
+
'option': false,
|
|
33
|
+
'addMargin': false,
|
|
34
|
+
'cancelAllOrders': true,
|
|
35
|
+
'cancelOrder': true,
|
|
36
|
+
'cancelOrders': true,
|
|
37
|
+
'createDepositAddress': true,
|
|
38
|
+
'createOrder': true,
|
|
39
|
+
'createStopLimitOrder': true,
|
|
40
|
+
'createStopMarketOrder': true,
|
|
41
|
+
'createTrailingAmountOrder': true,
|
|
42
|
+
'createStopOrder': true,
|
|
43
|
+
'editOrder': true,
|
|
44
|
+
'fetchBalance': true,
|
|
45
|
+
'fetchBorrowInterest': false,
|
|
46
|
+
'fetchBorrowRateHistories': false,
|
|
47
|
+
'fetchBorrowRateHistory': false,
|
|
48
|
+
'fetchClosedOrders': true,
|
|
49
|
+
'fetchCrossBorrowRate': false,
|
|
50
|
+
'fetchCrossBorrowRates': false,
|
|
51
|
+
'fetchCurrencies': true,
|
|
52
|
+
'fetchDepositAddress': true,
|
|
53
|
+
'fetchDeposits': true,
|
|
54
|
+
'fetchFundingHistory': false,
|
|
55
|
+
'fetchFundingRate': false,
|
|
56
|
+
'fetchFundingRateHistory': false,
|
|
57
|
+
'fetchFundingRates': false,
|
|
58
|
+
'fetchIndexOHLCV': false,
|
|
59
|
+
'fetchIsolatedBorrowRate': false,
|
|
60
|
+
'fetchIsolatedBorrowRates': false,
|
|
61
|
+
'fetchLedger': true,
|
|
62
|
+
'fetchLedgerEntry': true,
|
|
63
|
+
'fetchLeverageTiers': false,
|
|
64
|
+
'fetchMarkets': true,
|
|
65
|
+
'fetchMarkOHLCV': false,
|
|
66
|
+
'fetchMyTrades': true,
|
|
67
|
+
'fetchOHLCV': true,
|
|
68
|
+
'fetchOpenInterestHistory': false,
|
|
69
|
+
'fetchOpenOrders': true,
|
|
70
|
+
'fetchOrder': true,
|
|
71
|
+
'fetchOrderBook': true,
|
|
72
|
+
'fetchOrderTrades': 'emulated',
|
|
73
|
+
'fetchPositions': true,
|
|
74
|
+
'fetchPremiumIndexOHLCV': false,
|
|
75
|
+
'fetchTicker': true,
|
|
76
|
+
'fetchTickers': true,
|
|
77
|
+
'fetchTime': true,
|
|
78
|
+
'fetchTrades': true,
|
|
79
|
+
'fetchTradingFee': true,
|
|
80
|
+
'fetchTradingFees': false,
|
|
81
|
+
'fetchWithdrawals': true,
|
|
82
|
+
'setLeverage': false,
|
|
83
|
+
'setMarginMode': false,
|
|
84
|
+
'transfer': true,
|
|
85
|
+
'withdraw': true,
|
|
86
|
+
},
|
|
87
|
+
'timeframes': {
|
|
88
|
+
'1m': 1,
|
|
89
|
+
'5m': 5,
|
|
90
|
+
'15m': 15,
|
|
91
|
+
'30m': 30,
|
|
92
|
+
'1h': 60,
|
|
93
|
+
'4h': 240,
|
|
94
|
+
'1d': 1440,
|
|
95
|
+
'1w': 10080,
|
|
96
|
+
'2w': 21600,
|
|
97
|
+
},
|
|
98
|
+
'urls': {
|
|
99
|
+
'logo': 'https://user-images.githubusercontent.com/51840849/76173629-fc67fb00-61b1-11ea-84fe-f2de582f58a3.jpg',
|
|
100
|
+
'api': {
|
|
101
|
+
'public': 'https://api.kraken.com',
|
|
102
|
+
'private': 'https://api.kraken.com',
|
|
103
|
+
'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
|
|
104
|
+
},
|
|
105
|
+
'www': 'https://www.kraken.com',
|
|
106
|
+
'doc': 'https://www.kraken.com/features/api',
|
|
107
|
+
'fees': 'https://www.kraken.com/en-us/features/fee-schedule',
|
|
108
|
+
},
|
|
109
|
+
'fees': {
|
|
110
|
+
'trading': {
|
|
111
|
+
'tierBased': true,
|
|
112
|
+
'percentage': true,
|
|
113
|
+
'taker': this.parseNumber('0.0026'),
|
|
114
|
+
'maker': this.parseNumber('0.0016'),
|
|
115
|
+
'tiers': {
|
|
116
|
+
'taker': [
|
|
117
|
+
[this.parseNumber('0'), this.parseNumber('0.0026')],
|
|
118
|
+
[this.parseNumber('50000'), this.parseNumber('0.0024')],
|
|
119
|
+
[this.parseNumber('100000'), this.parseNumber('0.0022')],
|
|
120
|
+
[this.parseNumber('250000'), this.parseNumber('0.0020')],
|
|
121
|
+
[this.parseNumber('500000'), this.parseNumber('0.0018')],
|
|
122
|
+
[this.parseNumber('1000000'), this.parseNumber('0.0016')],
|
|
123
|
+
[this.parseNumber('2500000'), this.parseNumber('0.0014')],
|
|
124
|
+
[this.parseNumber('5000000'), this.parseNumber('0.0012')],
|
|
125
|
+
[this.parseNumber('10000000'), this.parseNumber('0.0001')],
|
|
126
|
+
],
|
|
127
|
+
'maker': [
|
|
128
|
+
[this.parseNumber('0'), this.parseNumber('0.0016')],
|
|
129
|
+
[this.parseNumber('50000'), this.parseNumber('0.0014')],
|
|
130
|
+
[this.parseNumber('100000'), this.parseNumber('0.0012')],
|
|
131
|
+
[this.parseNumber('250000'), this.parseNumber('0.0010')],
|
|
132
|
+
[this.parseNumber('500000'), this.parseNumber('0.0008')],
|
|
133
|
+
[this.parseNumber('1000000'), this.parseNumber('0.0006')],
|
|
134
|
+
[this.parseNumber('2500000'), this.parseNumber('0.0004')],
|
|
135
|
+
[this.parseNumber('5000000'), this.parseNumber('0.0002')],
|
|
136
|
+
[this.parseNumber('10000000'), this.parseNumber('0.0')],
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
'handleContentTypeApplicationZip': true,
|
|
142
|
+
'api': {
|
|
143
|
+
'zendesk': {
|
|
144
|
+
'get': [
|
|
145
|
+
// we should really refrain from putting fixed fee numbers and stop hardcoding
|
|
146
|
+
// we will be using their web APIs to scrape all numbers from these articles
|
|
147
|
+
'360000292886',
|
|
148
|
+
'201893608', // -What-are-the-withdrawal-fees-
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
'public': {
|
|
152
|
+
'get': {
|
|
153
|
+
// public endpoint rate-limits are described in article: https://support.kraken.com/hc/en-us/articles/206548367-What-are-the-API-rate-limits-#1
|
|
154
|
+
'Assets': 1,
|
|
155
|
+
'AssetPairs': 1,
|
|
156
|
+
'Depth': 1,
|
|
157
|
+
'OHLC': 1,
|
|
158
|
+
'Spread': 1,
|
|
159
|
+
'SystemStatus': 1,
|
|
160
|
+
'Ticker': 1,
|
|
161
|
+
'Time': 1,
|
|
162
|
+
'Trades': 1,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
'private': {
|
|
166
|
+
'post': {
|
|
167
|
+
'AddOrder': 0,
|
|
168
|
+
'AddOrderBatch': 0,
|
|
169
|
+
'AddExport': 3,
|
|
170
|
+
'Balance': 3,
|
|
171
|
+
'CancelAll': 3,
|
|
172
|
+
'CancelAllOrdersAfter': 3,
|
|
173
|
+
'CancelOrder': 0,
|
|
174
|
+
'CancelOrderBatch': 0,
|
|
175
|
+
'ClosedOrders': 6,
|
|
176
|
+
'DepositAddresses': 3,
|
|
177
|
+
'DepositMethods': 3,
|
|
178
|
+
'DepositStatus': 3,
|
|
179
|
+
'EditOrder': 0,
|
|
180
|
+
'ExportStatus': 3,
|
|
181
|
+
'GetWebSocketsToken': 3,
|
|
182
|
+
'Ledgers': 6,
|
|
183
|
+
'OpenOrders': 3,
|
|
184
|
+
'OpenPositions': 3,
|
|
185
|
+
'QueryLedgers': 3,
|
|
186
|
+
'QueryOrders': 3,
|
|
187
|
+
'QueryTrades': 3,
|
|
188
|
+
'RetrieveExport': 3,
|
|
189
|
+
'RemoveExport': 3,
|
|
190
|
+
'BalanceEx': 3,
|
|
191
|
+
'TradeBalance': 3,
|
|
192
|
+
'TradesHistory': 6,
|
|
193
|
+
'TradeVolume': 3,
|
|
194
|
+
'Withdraw': 3,
|
|
195
|
+
'WithdrawCancel': 3,
|
|
196
|
+
'WithdrawInfo': 3,
|
|
197
|
+
'WithdrawMethods': 3,
|
|
198
|
+
'WithdrawAddresses': 3,
|
|
199
|
+
'WithdrawStatus': 3,
|
|
200
|
+
'WalletTransfer': 3,
|
|
201
|
+
// sub accounts
|
|
202
|
+
'CreateSubaccount': 3,
|
|
203
|
+
'AccountTransfer': 3,
|
|
204
|
+
// earn
|
|
205
|
+
'Earn/Allocate': 3,
|
|
206
|
+
'Earn/Deallocate': 3,
|
|
207
|
+
'Earn/AllocateStatus': 3,
|
|
208
|
+
'Earn/DeallocateStatus': 3,
|
|
209
|
+
'Earn/Strategies': 3,
|
|
210
|
+
'Earn/Allocations': 3,
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
'commonCurrencies': {
|
|
215
|
+
'LUNA': 'LUNC',
|
|
216
|
+
'LUNA2': 'LUNA',
|
|
217
|
+
'REPV2': 'REP',
|
|
218
|
+
'REP': 'REPV1',
|
|
219
|
+
'UST': 'USTC',
|
|
220
|
+
'XBT': 'BTC',
|
|
221
|
+
'XBT.M': 'BTC.M',
|
|
222
|
+
'XDG': 'DOGE',
|
|
223
|
+
},
|
|
224
|
+
'options': {
|
|
225
|
+
'marketsByAltname': {},
|
|
226
|
+
'delistedMarketsById': {},
|
|
227
|
+
// cannot withdraw/deposit these
|
|
228
|
+
'inactiveCurrencies': ['CAD', 'USD', 'JPY', 'GBP'],
|
|
229
|
+
'networks': {
|
|
230
|
+
'ETH': 'ERC20',
|
|
231
|
+
'TRX': 'TRC20',
|
|
232
|
+
},
|
|
233
|
+
'depositMethods': {
|
|
234
|
+
'1INCH': '1inch (1INCH)',
|
|
235
|
+
'AAVE': 'Aave',
|
|
236
|
+
'ADA': 'ADA',
|
|
237
|
+
'ALGO': 'Algorand',
|
|
238
|
+
'ANKR': 'ANKR (ANKR)',
|
|
239
|
+
'ANT': 'Aragon (ANT)',
|
|
240
|
+
'ATOM': 'Cosmos',
|
|
241
|
+
'AXS': 'Axie Infinity Shards (AXS)',
|
|
242
|
+
'BADGER': 'Bager DAO (BADGER)',
|
|
243
|
+
'BAL': 'Balancer (BAL)',
|
|
244
|
+
'BAND': 'Band Protocol (BAND)',
|
|
245
|
+
'BAT': 'BAT',
|
|
246
|
+
'BCH': 'Bitcoin Cash',
|
|
247
|
+
'BNC': 'Bifrost (BNC)',
|
|
248
|
+
'BNT': 'Bancor (BNT)',
|
|
249
|
+
'BTC': 'Bitcoin',
|
|
250
|
+
'CHZ': 'Chiliz (CHZ)',
|
|
251
|
+
'COMP': 'Compound (COMP)',
|
|
252
|
+
'CQT': '\tCovalent Query Token (CQT)',
|
|
253
|
+
'CRV': 'Curve DAO Token (CRV)',
|
|
254
|
+
'CTSI': 'Cartesi (CTSI)',
|
|
255
|
+
'DAI': 'Dai',
|
|
256
|
+
'DASH': 'Dash',
|
|
257
|
+
'DOGE': 'Dogecoin',
|
|
258
|
+
'DOT': 'Polkadot',
|
|
259
|
+
'DYDX': 'dYdX (DYDX)',
|
|
260
|
+
'ENJ': 'Enjin Coin (ENJ)',
|
|
261
|
+
'EOS': 'EOS',
|
|
262
|
+
'ETC': 'Ether Classic (Hex)',
|
|
263
|
+
'ETH': 'Ether (Hex)',
|
|
264
|
+
'EWT': 'Energy Web Token',
|
|
265
|
+
'FEE': 'Kraken Fee Credit',
|
|
266
|
+
'FIL': 'Filecoin',
|
|
267
|
+
'FLOW': 'Flow',
|
|
268
|
+
'GHST': 'Aavegotchi (GHST)',
|
|
269
|
+
'GNO': 'GNO',
|
|
270
|
+
'GRT': 'GRT',
|
|
271
|
+
'ICX': 'Icon',
|
|
272
|
+
'INJ': 'Injective Protocol (INJ)',
|
|
273
|
+
'KAR': 'Karura (KAR)',
|
|
274
|
+
'KAVA': 'Kava',
|
|
275
|
+
'KEEP': 'Keep Token (KEEP)',
|
|
276
|
+
'KNC': 'Kyber Network (KNC)',
|
|
277
|
+
'KSM': 'Kusama',
|
|
278
|
+
'LINK': 'Link',
|
|
279
|
+
'LPT': 'Livepeer Token (LPT)',
|
|
280
|
+
'LRC': 'Loopring (LRC)',
|
|
281
|
+
'LSK': 'Lisk',
|
|
282
|
+
'LTC': 'Litecoin',
|
|
283
|
+
'MANA': 'MANA',
|
|
284
|
+
'MATIC': 'Polygon (MATIC)',
|
|
285
|
+
'MINA': 'Mina',
|
|
286
|
+
'MIR': 'Mirror Protocol (MIR)',
|
|
287
|
+
'MKR': 'Maker (MKR)',
|
|
288
|
+
'MLN': 'MLN',
|
|
289
|
+
'MOVR': 'Moonriver (MOVR)',
|
|
290
|
+
'NANO': 'NANO',
|
|
291
|
+
'OCEAN': 'OCEAN',
|
|
292
|
+
'OGN': 'Origin Protocol (OGN)',
|
|
293
|
+
'OMG': 'OMG',
|
|
294
|
+
'OXT': 'Orchid (OXT)',
|
|
295
|
+
'OXY': 'Oxygen (OXY)',
|
|
296
|
+
'PAXG': 'PAX (Gold)',
|
|
297
|
+
'PERP': 'Perpetual Protocol (PERP)',
|
|
298
|
+
'PHA': 'Phala (PHA)',
|
|
299
|
+
'QTUM': 'QTUM',
|
|
300
|
+
'RARI': 'Rarible (RARI)',
|
|
301
|
+
'RAY': 'Raydium (RAY)',
|
|
302
|
+
'REN': 'Ren Protocol (REN)',
|
|
303
|
+
'REP': 'REPv2',
|
|
304
|
+
'REPV1': 'REP',
|
|
305
|
+
'SAND': 'The Sandbox (SAND)',
|
|
306
|
+
'SC': 'Siacoin',
|
|
307
|
+
'SDN': 'Shiden (SDN)',
|
|
308
|
+
'SOL': 'Solana',
|
|
309
|
+
'SNX': 'Synthetix Network (SNX)',
|
|
310
|
+
'SRM': 'Serum',
|
|
311
|
+
'STORJ': 'Storj (STORJ)',
|
|
312
|
+
'SUSHI': 'Sushiswap (SUSHI)',
|
|
313
|
+
'TBTC': 'tBTC',
|
|
314
|
+
'TRX': 'Tron',
|
|
315
|
+
'UNI': 'UNI',
|
|
316
|
+
'USDC': 'USDC',
|
|
317
|
+
'USDT': 'Tether USD (ERC20)',
|
|
318
|
+
'USDT-TRC20': 'Tether USD (TRC20)',
|
|
319
|
+
'WAVES': 'Waves',
|
|
320
|
+
'WBTC': 'Wrapped Bitcoin (WBTC)',
|
|
321
|
+
'XLM': 'Stellar XLM',
|
|
322
|
+
'XMR': 'Monero',
|
|
323
|
+
'XRP': 'Ripple XRP',
|
|
324
|
+
'XTZ': 'XTZ',
|
|
325
|
+
'YFI': 'YFI',
|
|
326
|
+
'ZEC': 'Zcash (Transparent)',
|
|
327
|
+
'ZRX': '0x (ZRX)',
|
|
328
|
+
},
|
|
329
|
+
'withdrawMethods': {
|
|
330
|
+
'Lightning': 'Lightning',
|
|
331
|
+
'Bitcoin': 'BTC',
|
|
332
|
+
'Ripple': 'XRP',
|
|
333
|
+
'Litecoin': 'LTC',
|
|
334
|
+
'Dogecoin': 'DOGE',
|
|
335
|
+
'Stellar': 'XLM',
|
|
336
|
+
'Ethereum': 'ERC20',
|
|
337
|
+
'Arbitrum One': 'Arbitrum',
|
|
338
|
+
'Polygon': 'MATIC',
|
|
339
|
+
'Arbitrum Nova': 'Arbitrum',
|
|
340
|
+
'Optimism': 'Optimism',
|
|
341
|
+
'zkSync Era': 'zkSync',
|
|
342
|
+
'Ethereum Classic': 'ETC',
|
|
343
|
+
'Zcash': 'ZEC',
|
|
344
|
+
'Monero': 'XMR',
|
|
345
|
+
'Tron': 'TRC20',
|
|
346
|
+
'Solana': 'SOL',
|
|
347
|
+
'EOS': 'EOS',
|
|
348
|
+
'Bitcoin Cash': 'BCH',
|
|
349
|
+
'Cardano': 'ADA',
|
|
350
|
+
'Qtum': 'QTUM',
|
|
351
|
+
'Tezos': 'XTZ',
|
|
352
|
+
'Cosmos': 'ATOM',
|
|
353
|
+
'Nano': 'NANO',
|
|
354
|
+
'Siacoin': 'SC',
|
|
355
|
+
'Lisk': 'LSK',
|
|
356
|
+
'Waves': 'WAVES',
|
|
357
|
+
'ICON': 'ICX',
|
|
358
|
+
'Algorand': 'ALGO',
|
|
359
|
+
'Polygon - USDC.e': 'MATIC',
|
|
360
|
+
'Arbitrum One - USDC.e': 'Arbitrum',
|
|
361
|
+
'Polkadot': 'DOT',
|
|
362
|
+
'Kava': 'KAVA',
|
|
363
|
+
'Filecoin': 'FIL',
|
|
364
|
+
'Kusama': 'KSM',
|
|
365
|
+
'Flow': 'FLOW',
|
|
366
|
+
'Energy Web': 'EW',
|
|
367
|
+
'Mina': 'MINA',
|
|
368
|
+
'Centrifuge': 'CFG',
|
|
369
|
+
'Karura': 'KAR',
|
|
370
|
+
'Moonriver': 'MOVR',
|
|
371
|
+
'Shiden': 'SDN',
|
|
372
|
+
'Khala': 'PHA',
|
|
373
|
+
'Bifrost Kusama': 'BNC',
|
|
374
|
+
'Songbird': 'SGB',
|
|
375
|
+
'Terra classic': 'LUNC',
|
|
376
|
+
'KILT': 'KILT',
|
|
377
|
+
'Basilisk': 'BSX',
|
|
378
|
+
'Flare': 'FLR',
|
|
379
|
+
'Avalanche C-Chain': 'AVAX',
|
|
380
|
+
'Kintsugi': 'KINT',
|
|
381
|
+
'Altair': 'AIR',
|
|
382
|
+
'Moonbeam': 'GLMR',
|
|
383
|
+
'Acala': 'ACA',
|
|
384
|
+
'Astar': 'ASTR',
|
|
385
|
+
'Akash': 'AKT',
|
|
386
|
+
'Robonomics': 'XRT',
|
|
387
|
+
'Fantom': 'FTM',
|
|
388
|
+
'Elrond': 'EGLD',
|
|
389
|
+
'THORchain': 'RUNE',
|
|
390
|
+
'Secret': 'SCRT',
|
|
391
|
+
'Near': 'NEAR',
|
|
392
|
+
'Internet Computer Protocol': 'ICP',
|
|
393
|
+
'Picasso': 'PICA',
|
|
394
|
+
'Crust Shadow': 'CSM',
|
|
395
|
+
'Integritee': 'TEER',
|
|
396
|
+
'Parallel Finance': 'PARA',
|
|
397
|
+
'HydraDX': 'HDX',
|
|
398
|
+
'Interlay': 'INTR',
|
|
399
|
+
'Fetch.ai': 'FET',
|
|
400
|
+
'NYM': 'NYM',
|
|
401
|
+
'Terra 2.0': 'LUNA2',
|
|
402
|
+
'Juno': 'JUNO',
|
|
403
|
+
'Nodle': 'NODL',
|
|
404
|
+
'Stacks': 'STX',
|
|
405
|
+
'Ethereum PoW': 'ETHW',
|
|
406
|
+
'Aptos': 'APT',
|
|
407
|
+
'Sui': 'SUI',
|
|
408
|
+
'Genshiro': 'GENS',
|
|
409
|
+
'Aventus': 'AVT',
|
|
410
|
+
'Sei': 'SEI',
|
|
411
|
+
'OriginTrail': 'OTP',
|
|
412
|
+
'Celestia': 'TIA',
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
'precisionMode': number.TICK_SIZE,
|
|
416
|
+
'exceptions': {
|
|
417
|
+
'EQuery:Invalid asset pair': errors.BadSymbol,
|
|
418
|
+
'EAPI:Invalid key': errors.AuthenticationError,
|
|
419
|
+
'EFunding:Unknown withdraw key': errors.InvalidAddress,
|
|
420
|
+
'EFunding:Invalid amount': errors.InsufficientFunds,
|
|
421
|
+
'EService:Unavailable': errors.ExchangeNotAvailable,
|
|
422
|
+
'EDatabase:Internal error': errors.ExchangeNotAvailable,
|
|
423
|
+
'EService:Busy': errors.ExchangeNotAvailable,
|
|
424
|
+
'EQuery:Unknown asset': errors.BadSymbol,
|
|
425
|
+
'EAPI:Rate limit exceeded': errors.DDoSProtection,
|
|
426
|
+
'EOrder:Rate limit exceeded': errors.DDoSProtection,
|
|
427
|
+
'EGeneral:Internal error': errors.ExchangeNotAvailable,
|
|
428
|
+
'EGeneral:Temporary lockout': errors.DDoSProtection,
|
|
429
|
+
'EGeneral:Permission denied': errors.PermissionDenied,
|
|
430
|
+
'EOrder:Unknown order': errors.InvalidOrder,
|
|
431
|
+
'EOrder:Order minimum not met': errors.InvalidOrder,
|
|
432
|
+
'EGeneral:Invalid arguments': errors.BadRequest,
|
|
433
|
+
'ESession:Invalid session': errors.AuthenticationError,
|
|
434
|
+
'EAPI:Invalid nonce': errors.InvalidNonce,
|
|
435
|
+
'EFunding:No funding method': errors.BadRequest,
|
|
436
|
+
'EFunding:Unknown asset': errors.BadSymbol,
|
|
437
|
+
'EService:Market in post_only mode': errors.OnMaintenance,
|
|
438
|
+
'EGeneral:Too many requests': errors.DDoSProtection,
|
|
439
|
+
'ETrade:User Locked': errors.AccountSuspended, // {"error":["ETrade:User Locked"]}
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
feeToPrecision(symbol, fee) {
|
|
444
|
+
return this.decimalToPrecision(fee, number.TRUNCATE, this.markets[symbol]['precision']['amount'], this.precisionMode);
|
|
445
|
+
}
|
|
446
|
+
async fetchMarkets(params = {}) {
|
|
447
|
+
/**
|
|
448
|
+
* @method
|
|
449
|
+
* @name kraken#fetchMarkets
|
|
450
|
+
* @description retrieves data on all markets for kraken
|
|
451
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getTradableAssetPairs
|
|
452
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
453
|
+
* @returns {object[]} an array of objects representing market data
|
|
454
|
+
*/
|
|
455
|
+
const response = await this.publicGetAssetPairs(params);
|
|
456
|
+
//
|
|
457
|
+
// {
|
|
458
|
+
// "error": [],
|
|
459
|
+
// "result": {
|
|
460
|
+
// "ADAETH": {
|
|
461
|
+
// "altname": "ADAETH",
|
|
462
|
+
// "wsname": "ADA\/ETH",
|
|
463
|
+
// "aclass_base": "currency",
|
|
464
|
+
// "base": "ADA",
|
|
465
|
+
// "aclass_quote": "currency",
|
|
466
|
+
// "quote": "XETH",
|
|
467
|
+
// "lot": "unit",
|
|
468
|
+
// "pair_decimals": 7,
|
|
469
|
+
// "lot_decimals": 8,
|
|
470
|
+
// "lot_multiplier": 1,
|
|
471
|
+
// "leverage_buy": [],
|
|
472
|
+
// "leverage_sell": [],
|
|
473
|
+
// "fees": [
|
|
474
|
+
// [0, 0.26],
|
|
475
|
+
// [50000, 0.24],
|
|
476
|
+
// [100000, 0.22],
|
|
477
|
+
// [250000, 0.2],
|
|
478
|
+
// [500000, 0.18],
|
|
479
|
+
// [1000000, 0.16],
|
|
480
|
+
// [2500000, 0.14],
|
|
481
|
+
// [5000000, 0.12],
|
|
482
|
+
// [10000000, 0.1]
|
|
483
|
+
// ],
|
|
484
|
+
// "fees_maker": [
|
|
485
|
+
// [0, 0.16],
|
|
486
|
+
// [50000, 0.14],
|
|
487
|
+
// [100000, 0.12],
|
|
488
|
+
// [250000, 0.1],
|
|
489
|
+
// [500000, 0.08],
|
|
490
|
+
// [1000000, 0.06],
|
|
491
|
+
// [2500000, 0.04],
|
|
492
|
+
// [5000000, 0.02],
|
|
493
|
+
// [10000000, 0]
|
|
494
|
+
// ],
|
|
495
|
+
// "fee_volume_currency": "ZUSD",
|
|
496
|
+
// "margin_call": 80,
|
|
497
|
+
// "margin_stop": 40,
|
|
498
|
+
// "ordermin": "1"
|
|
499
|
+
// },
|
|
500
|
+
// }
|
|
501
|
+
// }
|
|
502
|
+
//
|
|
503
|
+
const markets = this.safeValue(response, 'result', {});
|
|
504
|
+
const keys = Object.keys(markets);
|
|
505
|
+
let result = [];
|
|
506
|
+
for (let i = 0; i < keys.length; i++) {
|
|
507
|
+
const id = keys[i];
|
|
508
|
+
const market = markets[id];
|
|
509
|
+
const baseId = this.safeString(market, 'base');
|
|
510
|
+
const quoteId = this.safeString(market, 'quote');
|
|
511
|
+
const base = this.safeCurrencyCode(baseId);
|
|
512
|
+
const quote = this.safeCurrencyCode(quoteId);
|
|
513
|
+
const darkpool = id.indexOf('.d') >= 0;
|
|
514
|
+
const altname = this.safeString(market, 'altname');
|
|
515
|
+
const makerFees = this.safeValue(market, 'fees_maker', []);
|
|
516
|
+
const firstMakerFee = this.safeValue(makerFees, 0, []);
|
|
517
|
+
const firstMakerFeeRate = this.safeString(firstMakerFee, 1);
|
|
518
|
+
let maker = undefined;
|
|
519
|
+
if (firstMakerFeeRate !== undefined) {
|
|
520
|
+
maker = this.parseNumber(Precise["default"].stringDiv(firstMakerFeeRate, '100'));
|
|
521
|
+
}
|
|
522
|
+
const takerFees = this.safeValue(market, 'fees', []);
|
|
523
|
+
const firstTakerFee = this.safeValue(takerFees, 0, []);
|
|
524
|
+
const firstTakerFeeRate = this.safeString(firstTakerFee, 1);
|
|
525
|
+
let taker = undefined;
|
|
526
|
+
if (firstTakerFeeRate !== undefined) {
|
|
527
|
+
taker = this.parseNumber(Precise["default"].stringDiv(firstTakerFeeRate, '100'));
|
|
528
|
+
}
|
|
529
|
+
const leverageBuy = this.safeValue(market, 'leverage_buy', []);
|
|
530
|
+
const leverageBuyLength = leverageBuy.length;
|
|
531
|
+
const precisionPrice = this.parseNumber(this.parsePrecision(this.safeString(market, 'pair_decimals')));
|
|
532
|
+
result.push({
|
|
533
|
+
'id': id,
|
|
534
|
+
'wsId': this.safeString(market, 'wsname'),
|
|
535
|
+
'symbol': darkpool ? altname : (base + '/' + quote),
|
|
536
|
+
'base': base,
|
|
537
|
+
'quote': quote,
|
|
538
|
+
'settle': undefined,
|
|
539
|
+
'baseId': baseId,
|
|
540
|
+
'quoteId': quoteId,
|
|
541
|
+
'settleId': undefined,
|
|
542
|
+
'darkpool': darkpool,
|
|
543
|
+
'altname': market['altname'],
|
|
544
|
+
'type': 'spot',
|
|
545
|
+
'spot': true,
|
|
546
|
+
'margin': (leverageBuyLength > 0),
|
|
547
|
+
'swap': false,
|
|
548
|
+
'future': false,
|
|
549
|
+
'option': false,
|
|
550
|
+
'active': true,
|
|
551
|
+
'contract': false,
|
|
552
|
+
'linear': undefined,
|
|
553
|
+
'inverse': undefined,
|
|
554
|
+
'taker': taker,
|
|
555
|
+
'maker': maker,
|
|
556
|
+
'contractSize': undefined,
|
|
557
|
+
'expiry': undefined,
|
|
558
|
+
'expiryDatetime': undefined,
|
|
559
|
+
'strike': undefined,
|
|
560
|
+
'optionType': undefined,
|
|
561
|
+
'precision': {
|
|
562
|
+
'amount': this.parseNumber(this.parsePrecision(this.safeString(market, 'lot_decimals'))),
|
|
563
|
+
'price': precisionPrice,
|
|
564
|
+
},
|
|
565
|
+
'limits': {
|
|
566
|
+
'leverage': {
|
|
567
|
+
'min': this.parseNumber('1'),
|
|
568
|
+
'max': this.safeNumber(leverageBuy, leverageBuyLength - 1, 1),
|
|
569
|
+
},
|
|
570
|
+
'amount': {
|
|
571
|
+
'min': this.safeNumber(market, 'ordermin'),
|
|
572
|
+
'max': undefined,
|
|
573
|
+
},
|
|
574
|
+
'price': {
|
|
575
|
+
'min': precisionPrice,
|
|
576
|
+
'max': undefined,
|
|
577
|
+
},
|
|
578
|
+
'cost': {
|
|
579
|
+
'min': this.safeNumber(market, 'costmin'),
|
|
580
|
+
'max': undefined,
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
'created': undefined,
|
|
584
|
+
'info': market,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
result = this.appendInactiveMarkets(result);
|
|
588
|
+
this.options['marketsByAltname'] = this.indexBy(result, 'altname');
|
|
589
|
+
return result;
|
|
590
|
+
}
|
|
591
|
+
safeCurrency(currencyId, currency = undefined) {
|
|
592
|
+
if (currencyId !== undefined) {
|
|
593
|
+
if (currencyId.length > 3) {
|
|
594
|
+
if ((currencyId.indexOf('X') === 0) || (currencyId.indexOf('Z') === 0)) {
|
|
595
|
+
if (currencyId.indexOf('.') > 0) {
|
|
596
|
+
return super.safeCurrency(currencyId, currency);
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
currencyId = currencyId.slice(1);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
return super.safeCurrency(currencyId, currency);
|
|
605
|
+
}
|
|
606
|
+
appendInactiveMarkets(result) {
|
|
607
|
+
// result should be an array to append to
|
|
608
|
+
const precision = {
|
|
609
|
+
'amount': this.parseNumber('1e-8'),
|
|
610
|
+
'price': this.parseNumber('1e-8'),
|
|
611
|
+
};
|
|
612
|
+
const costLimits = { 'min': undefined, 'max': undefined };
|
|
613
|
+
const priceLimits = { 'min': precision['price'], 'max': undefined };
|
|
614
|
+
const amountLimits = { 'min': precision['amount'], 'max': undefined };
|
|
615
|
+
const limits = { 'amount': amountLimits, 'price': priceLimits, 'cost': costLimits };
|
|
616
|
+
const defaults = {
|
|
617
|
+
'darkpool': false,
|
|
618
|
+
'info': undefined,
|
|
619
|
+
'maker': undefined,
|
|
620
|
+
'taker': undefined,
|
|
621
|
+
'active': false,
|
|
622
|
+
'precision': precision,
|
|
623
|
+
'limits': limits,
|
|
624
|
+
};
|
|
625
|
+
const markets = [
|
|
626
|
+
// { 'id': 'XXLMZEUR', 'symbol': 'XLM/EUR', 'base': 'XLM', 'quote': 'EUR', 'altname': 'XLMEUR' },
|
|
627
|
+
];
|
|
628
|
+
for (let i = 0; i < markets.length; i++) {
|
|
629
|
+
result.push(this.extend(defaults, markets[i]));
|
|
630
|
+
}
|
|
631
|
+
return result;
|
|
632
|
+
}
|
|
633
|
+
async fetchCurrencies(params = {}) {
|
|
634
|
+
/**
|
|
635
|
+
* @method
|
|
636
|
+
* @name kraken#fetchCurrencies
|
|
637
|
+
* @description fetches all available currencies on an exchange
|
|
638
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getAssetInfo
|
|
639
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
640
|
+
* @returns {object} an associative dictionary of currencies
|
|
641
|
+
*/
|
|
642
|
+
const response = await this.publicGetAssets(params);
|
|
643
|
+
//
|
|
644
|
+
// {
|
|
645
|
+
// "error": [],
|
|
646
|
+
// "result": {
|
|
647
|
+
// "ADA": { "aclass": "currency", "altname": "ADA", "decimals": 8, "display_decimals": 6 },
|
|
648
|
+
// "BCH": { "aclass": "currency", "altname": "BCH", "decimals": 10, "display_decimals": 5 },
|
|
649
|
+
// ...
|
|
650
|
+
// },
|
|
651
|
+
// }
|
|
652
|
+
//
|
|
653
|
+
const currencies = this.safeValue(response, 'result', {});
|
|
654
|
+
const ids = Object.keys(currencies);
|
|
655
|
+
const result = {};
|
|
656
|
+
for (let i = 0; i < ids.length; i++) {
|
|
657
|
+
const id = ids[i];
|
|
658
|
+
const currency = currencies[id];
|
|
659
|
+
// todo: will need to rethink the fees
|
|
660
|
+
// see: https://support.kraken.com/hc/en-us/articles/201893608-What-are-the-withdrawal-fees-
|
|
661
|
+
// to add support for multiple withdrawal/deposit methods and
|
|
662
|
+
// differentiated fees for each particular method
|
|
663
|
+
const code = this.safeCurrencyCode(this.safeString(currency, 'altname'));
|
|
664
|
+
const precision = this.parseNumber(this.parsePrecision(this.safeString(currency, 'decimals')));
|
|
665
|
+
// assumes all currencies are active except those listed above
|
|
666
|
+
const active = !this.inArray(code, this.options['inactiveCurrencies']);
|
|
667
|
+
result[code] = {
|
|
668
|
+
'id': id,
|
|
669
|
+
'code': code,
|
|
670
|
+
'info': currency,
|
|
671
|
+
'name': code,
|
|
672
|
+
'active': active,
|
|
673
|
+
'deposit': undefined,
|
|
674
|
+
'withdraw': undefined,
|
|
675
|
+
'fee': undefined,
|
|
676
|
+
'precision': precision,
|
|
677
|
+
'limits': {
|
|
678
|
+
'amount': {
|
|
679
|
+
'min': precision,
|
|
680
|
+
'max': undefined,
|
|
681
|
+
},
|
|
682
|
+
'withdraw': {
|
|
683
|
+
'min': undefined,
|
|
684
|
+
'max': undefined,
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
'networks': {},
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
return result;
|
|
691
|
+
}
|
|
692
|
+
async fetchTradingFee(symbol, params = {}) {
|
|
693
|
+
/**
|
|
694
|
+
* @method
|
|
695
|
+
* @name kraken#fetchTradingFee
|
|
696
|
+
* @description fetch the trading fees for a market
|
|
697
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getTradeVolume
|
|
698
|
+
* @param {string} symbol unified market symbol
|
|
699
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
700
|
+
* @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
|
|
701
|
+
*/
|
|
702
|
+
await this.loadMarkets();
|
|
703
|
+
const market = this.market(symbol);
|
|
704
|
+
const request = {
|
|
705
|
+
'pair': market['id'],
|
|
706
|
+
'fee-info': true,
|
|
707
|
+
};
|
|
708
|
+
const response = await this.privatePostTradeVolume(this.extend(request, params));
|
|
709
|
+
//
|
|
710
|
+
// {
|
|
711
|
+
// "error": [],
|
|
712
|
+
// "result": {
|
|
713
|
+
// "currency": 'ZUSD',
|
|
714
|
+
// "volume": '0.0000',
|
|
715
|
+
// "fees": {
|
|
716
|
+
// "XXBTZUSD": {
|
|
717
|
+
// "fee": '0.2600',
|
|
718
|
+
// "minfee": '0.1000',
|
|
719
|
+
// "maxfee": '0.2600',
|
|
720
|
+
// "nextfee": '0.2400',
|
|
721
|
+
// "tiervolume": '0.0000',
|
|
722
|
+
// "nextvolume": '50000.0000'
|
|
723
|
+
// }
|
|
724
|
+
// },
|
|
725
|
+
// "fees_maker": {
|
|
726
|
+
// "XXBTZUSD": {
|
|
727
|
+
// "fee": '0.1600',
|
|
728
|
+
// "minfee": '0.0000',
|
|
729
|
+
// "maxfee": '0.1600',
|
|
730
|
+
// "nextfee": '0.1400',
|
|
731
|
+
// "tiervolume": '0.0000',
|
|
732
|
+
// "nextvolume": '50000.0000'
|
|
733
|
+
// }
|
|
734
|
+
// }
|
|
735
|
+
// }
|
|
736
|
+
// }
|
|
737
|
+
//
|
|
738
|
+
const result = this.safeValue(response, 'result', {});
|
|
739
|
+
return this.parseTradingFee(result, market);
|
|
740
|
+
}
|
|
741
|
+
parseTradingFee(response, market) {
|
|
742
|
+
const makerFees = this.safeValue(response, 'fees_maker', {});
|
|
743
|
+
const takerFees = this.safeValue(response, 'fees', {});
|
|
744
|
+
const symbolMakerFee = this.safeValue(makerFees, market['id'], {});
|
|
745
|
+
const symbolTakerFee = this.safeValue(takerFees, market['id'], {});
|
|
746
|
+
return {
|
|
747
|
+
'info': response,
|
|
748
|
+
'symbol': market['symbol'],
|
|
749
|
+
'maker': this.safeNumber(symbolMakerFee, 'fee'),
|
|
750
|
+
'taker': this.safeNumber(symbolTakerFee, 'fee'),
|
|
751
|
+
'percentage': true,
|
|
752
|
+
'tierBased': true,
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
parseBidAsk(bidask, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
|
|
756
|
+
const price = this.safeNumber(bidask, priceKey);
|
|
757
|
+
const amount = this.safeNumber(bidask, amountKey);
|
|
758
|
+
const timestamp = this.safeInteger(bidask, 2);
|
|
759
|
+
return [price, amount, timestamp];
|
|
760
|
+
}
|
|
761
|
+
async fetchOrderBook(symbol, limit = undefined, params = {}) {
|
|
762
|
+
/**
|
|
763
|
+
* @method
|
|
764
|
+
* @name kraken#fetchOrderBook
|
|
765
|
+
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
766
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getOrderBook
|
|
767
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
768
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
769
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
770
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
771
|
+
*/
|
|
772
|
+
await this.loadMarkets();
|
|
773
|
+
const market = this.market(symbol);
|
|
774
|
+
if (market['darkpool']) {
|
|
775
|
+
throw new errors.ExchangeError(this.id + ' fetchOrderBook() does not provide an order book for darkpool symbol ' + symbol);
|
|
776
|
+
}
|
|
777
|
+
const request = {
|
|
778
|
+
'pair': market['id'],
|
|
779
|
+
};
|
|
780
|
+
if (limit !== undefined) {
|
|
781
|
+
request['count'] = limit; // 100
|
|
782
|
+
}
|
|
783
|
+
const response = await this.publicGetDepth(this.extend(request, params));
|
|
784
|
+
//
|
|
785
|
+
// {
|
|
786
|
+
// "error":[],
|
|
787
|
+
// "result":{
|
|
788
|
+
// "XETHXXBT":{
|
|
789
|
+
// "asks":[
|
|
790
|
+
// ["0.023480","4.000",1586321307],
|
|
791
|
+
// ["0.023490","50.095",1586321306],
|
|
792
|
+
// ["0.023500","28.535",1586321302],
|
|
793
|
+
// ],
|
|
794
|
+
// "bids":[
|
|
795
|
+
// ["0.023470","59.580",1586321307],
|
|
796
|
+
// ["0.023460","20.000",1586321301],
|
|
797
|
+
// ["0.023440","67.832",1586321306],
|
|
798
|
+
// ]
|
|
799
|
+
// }
|
|
800
|
+
// }
|
|
801
|
+
// }
|
|
802
|
+
//
|
|
803
|
+
const result = this.safeValue(response, 'result', {});
|
|
804
|
+
let orderbook = this.safeValue(result, market['id']);
|
|
805
|
+
// sometimes kraken returns wsname instead of market id
|
|
806
|
+
// https://github.com/ccxt/ccxt/issues/8662
|
|
807
|
+
const marketInfo = this.safeValue(market, 'info', {});
|
|
808
|
+
const wsName = this.safeValue(marketInfo, 'wsname');
|
|
809
|
+
if (wsName !== undefined) {
|
|
810
|
+
orderbook = this.safeValue(result, wsName, orderbook);
|
|
811
|
+
}
|
|
812
|
+
return this.parseOrderBook(orderbook, symbol);
|
|
813
|
+
}
|
|
814
|
+
parseTicker(ticker, market = undefined) {
|
|
815
|
+
//
|
|
816
|
+
// {
|
|
817
|
+
// "a":["2432.77000","1","1.000"],
|
|
818
|
+
// "b":["2431.37000","2","2.000"],
|
|
819
|
+
// "c":["2430.58000","0.04408910"],
|
|
820
|
+
// "v":["4147.94474901","8896.96086304"],
|
|
821
|
+
// "p":["2456.22239","2568.63032"],
|
|
822
|
+
// "t":[3907,10056],
|
|
823
|
+
// "l":["2302.18000","2302.18000"],
|
|
824
|
+
// "h":["2621.14000","2860.01000"],
|
|
825
|
+
// "o":"2571.56000"
|
|
826
|
+
// }
|
|
827
|
+
//
|
|
828
|
+
const symbol = this.safeSymbol(undefined, market);
|
|
829
|
+
const v = this.safeValue(ticker, 'v', []);
|
|
830
|
+
const baseVolume = this.safeString(v, 1);
|
|
831
|
+
const p = this.safeValue(ticker, 'p', []);
|
|
832
|
+
const vwap = this.safeString(p, 1);
|
|
833
|
+
const quoteVolume = Precise["default"].stringMul(baseVolume, vwap);
|
|
834
|
+
const c = this.safeValue(ticker, 'c', []);
|
|
835
|
+
const last = this.safeString(c, 0);
|
|
836
|
+
const high = this.safeValue(ticker, 'h', []);
|
|
837
|
+
const low = this.safeValue(ticker, 'l', []);
|
|
838
|
+
const bid = this.safeValue(ticker, 'b', []);
|
|
839
|
+
const ask = this.safeValue(ticker, 'a', []);
|
|
840
|
+
return this.safeTicker({
|
|
841
|
+
'symbol': symbol,
|
|
842
|
+
'timestamp': undefined,
|
|
843
|
+
'datetime': undefined,
|
|
844
|
+
'high': this.safeString(high, 1),
|
|
845
|
+
'low': this.safeString(low, 1),
|
|
846
|
+
'bid': this.safeString(bid, 0),
|
|
847
|
+
'bidVolume': undefined,
|
|
848
|
+
'ask': this.safeString(ask, 0),
|
|
849
|
+
'askVolume': undefined,
|
|
850
|
+
'vwap': vwap,
|
|
851
|
+
'open': this.safeString(ticker, 'o'),
|
|
852
|
+
'close': last,
|
|
853
|
+
'last': last,
|
|
854
|
+
'previousClose': undefined,
|
|
855
|
+
'change': undefined,
|
|
856
|
+
'percentage': undefined,
|
|
857
|
+
'average': undefined,
|
|
858
|
+
'baseVolume': baseVolume,
|
|
859
|
+
'quoteVolume': quoteVolume,
|
|
860
|
+
'info': ticker,
|
|
861
|
+
}, market);
|
|
862
|
+
}
|
|
863
|
+
async fetchTickers(symbols = undefined, params = {}) {
|
|
864
|
+
/**
|
|
865
|
+
* @method
|
|
866
|
+
* @name kraken#fetchTickers
|
|
867
|
+
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
|
868
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getTickerInformation
|
|
869
|
+
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
|
870
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
871
|
+
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
872
|
+
*/
|
|
873
|
+
await this.loadMarkets();
|
|
874
|
+
const request = {};
|
|
875
|
+
if (symbols !== undefined) {
|
|
876
|
+
symbols = this.marketSymbols(symbols);
|
|
877
|
+
const marketIds = [];
|
|
878
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
879
|
+
const symbol = symbols[i];
|
|
880
|
+
const market = this.markets[symbol];
|
|
881
|
+
if (market['active'] && !market['darkpool']) {
|
|
882
|
+
marketIds.push(market['id']);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
request['pair'] = marketIds.join(',');
|
|
886
|
+
}
|
|
887
|
+
const response = await this.publicGetTicker(this.extend(request, params));
|
|
888
|
+
const tickers = response['result'];
|
|
889
|
+
const ids = Object.keys(tickers);
|
|
890
|
+
const result = {};
|
|
891
|
+
for (let i = 0; i < ids.length; i++) {
|
|
892
|
+
const id = ids[i];
|
|
893
|
+
const market = this.safeMarket(id);
|
|
894
|
+
const symbol = market['symbol'];
|
|
895
|
+
const ticker = tickers[id];
|
|
896
|
+
result[symbol] = this.parseTicker(ticker, market);
|
|
897
|
+
}
|
|
898
|
+
return this.filterByArrayTickers(result, 'symbol', symbols);
|
|
899
|
+
}
|
|
900
|
+
async fetchTicker(symbol, params = {}) {
|
|
901
|
+
/**
|
|
902
|
+
* @method
|
|
903
|
+
* @name kraken#fetchTicker
|
|
904
|
+
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
905
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getTickerInformation
|
|
906
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
907
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
908
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
909
|
+
*/
|
|
910
|
+
await this.loadMarkets();
|
|
911
|
+
const darkpool = symbol.indexOf('.d') >= 0;
|
|
912
|
+
if (darkpool) {
|
|
913
|
+
throw new errors.ExchangeError(this.id + ' fetchTicker() does not provide a ticker for darkpool symbol ' + symbol);
|
|
914
|
+
}
|
|
915
|
+
const market = this.market(symbol);
|
|
916
|
+
const request = {
|
|
917
|
+
'pair': market['id'],
|
|
918
|
+
};
|
|
919
|
+
const response = await this.publicGetTicker(this.extend(request, params));
|
|
920
|
+
const ticker = response['result'][market['id']];
|
|
921
|
+
return this.parseTicker(ticker, market);
|
|
922
|
+
}
|
|
923
|
+
parseOHLCV(ohlcv, market = undefined) {
|
|
924
|
+
//
|
|
925
|
+
// [
|
|
926
|
+
// 1591475640,
|
|
927
|
+
// "0.02500",
|
|
928
|
+
// "0.02500",
|
|
929
|
+
// "0.02500",
|
|
930
|
+
// "0.02500",
|
|
931
|
+
// "0.02500",
|
|
932
|
+
// "9.12201000",
|
|
933
|
+
// 5
|
|
934
|
+
// ]
|
|
935
|
+
//
|
|
936
|
+
return [
|
|
937
|
+
this.safeTimestamp(ohlcv, 0),
|
|
938
|
+
this.safeNumber(ohlcv, 1),
|
|
939
|
+
this.safeNumber(ohlcv, 2),
|
|
940
|
+
this.safeNumber(ohlcv, 3),
|
|
941
|
+
this.safeNumber(ohlcv, 4),
|
|
942
|
+
this.safeNumber(ohlcv, 6),
|
|
943
|
+
];
|
|
944
|
+
}
|
|
945
|
+
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
946
|
+
/**
|
|
947
|
+
* @method
|
|
948
|
+
* @name kraken#fetchOHLCV
|
|
949
|
+
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
950
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getOHLCData
|
|
951
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
952
|
+
* @param {string} timeframe the length of time each candle represents
|
|
953
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
954
|
+
* @param {int} [limit] the maximum amount of candles to fetch
|
|
955
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
956
|
+
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
|
957
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
958
|
+
*/
|
|
959
|
+
await this.loadMarkets();
|
|
960
|
+
let paginate = false;
|
|
961
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate');
|
|
962
|
+
if (paginate) {
|
|
963
|
+
return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 720);
|
|
964
|
+
}
|
|
965
|
+
const market = this.market(symbol);
|
|
966
|
+
const parsedTimeframe = this.safeInteger(this.timeframes, timeframe);
|
|
967
|
+
const request = {
|
|
968
|
+
'pair': market['id'],
|
|
969
|
+
};
|
|
970
|
+
if (parsedTimeframe !== undefined) {
|
|
971
|
+
request['interval'] = parsedTimeframe;
|
|
972
|
+
}
|
|
973
|
+
else {
|
|
974
|
+
request['interval'] = timeframe;
|
|
975
|
+
}
|
|
976
|
+
if (since !== undefined) {
|
|
977
|
+
request['since'] = this.parseToInt((since - 1) / 1000);
|
|
978
|
+
}
|
|
979
|
+
const response = await this.publicGetOHLC(this.extend(request, params));
|
|
980
|
+
//
|
|
981
|
+
// {
|
|
982
|
+
// "error":[],
|
|
983
|
+
// "result":{
|
|
984
|
+
// "XETHXXBT":[
|
|
985
|
+
// [1591475580,"0.02499","0.02499","0.02499","0.02499","0.00000","0.00000000",0],
|
|
986
|
+
// [1591475640,"0.02500","0.02500","0.02500","0.02500","0.02500","9.12201000",5],
|
|
987
|
+
// [1591475700,"0.02499","0.02499","0.02499","0.02499","0.02499","1.28681415",2],
|
|
988
|
+
// [1591475760,"0.02499","0.02499","0.02499","0.02499","0.02499","0.08800000",1],
|
|
989
|
+
// ],
|
|
990
|
+
// "last":1591517580
|
|
991
|
+
// }
|
|
992
|
+
// }
|
|
993
|
+
const result = this.safeValue(response, 'result', {});
|
|
994
|
+
const ohlcvs = this.safeValue(result, market['id'], []);
|
|
995
|
+
return this.parseOHLCVs(ohlcvs, market, timeframe, since, limit);
|
|
996
|
+
}
|
|
997
|
+
parseLedgerEntryType(type) {
|
|
998
|
+
const types = {
|
|
999
|
+
'trade': 'trade',
|
|
1000
|
+
'withdrawal': 'transaction',
|
|
1001
|
+
'deposit': 'transaction',
|
|
1002
|
+
'transfer': 'transfer',
|
|
1003
|
+
'margin': 'margin',
|
|
1004
|
+
};
|
|
1005
|
+
return this.safeString(types, type, type);
|
|
1006
|
+
}
|
|
1007
|
+
parseLedgerEntry(item, currency = undefined) {
|
|
1008
|
+
//
|
|
1009
|
+
// {
|
|
1010
|
+
// 'LTFK7F-N2CUX-PNY4SX': {
|
|
1011
|
+
// "refid": "TSJTGT-DT7WN-GPPQMJ",
|
|
1012
|
+
// "time": 1520102320.555,
|
|
1013
|
+
// "type": "trade",
|
|
1014
|
+
// "aclass": "currency",
|
|
1015
|
+
// "asset": "XETH",
|
|
1016
|
+
// "amount": "0.1087194600",
|
|
1017
|
+
// "fee": "0.0000000000",
|
|
1018
|
+
// "balance": "0.2855851000"
|
|
1019
|
+
// },
|
|
1020
|
+
// ...
|
|
1021
|
+
// }
|
|
1022
|
+
//
|
|
1023
|
+
const id = this.safeString(item, 'id');
|
|
1024
|
+
let direction = undefined;
|
|
1025
|
+
const account = undefined;
|
|
1026
|
+
const referenceId = this.safeString(item, 'refid');
|
|
1027
|
+
const referenceAccount = undefined;
|
|
1028
|
+
const type = this.parseLedgerEntryType(this.safeString(item, 'type'));
|
|
1029
|
+
const code = this.safeCurrencyCode(this.safeString(item, 'asset'), currency);
|
|
1030
|
+
let amount = this.safeString(item, 'amount');
|
|
1031
|
+
if (Precise["default"].stringLt(amount, '0')) {
|
|
1032
|
+
direction = 'out';
|
|
1033
|
+
amount = Precise["default"].stringAbs(amount);
|
|
1034
|
+
}
|
|
1035
|
+
else {
|
|
1036
|
+
direction = 'in';
|
|
1037
|
+
}
|
|
1038
|
+
const timestamp = this.safeTimestamp(item, 'time');
|
|
1039
|
+
return {
|
|
1040
|
+
'info': item,
|
|
1041
|
+
'id': id,
|
|
1042
|
+
'direction': direction,
|
|
1043
|
+
'account': account,
|
|
1044
|
+
'referenceId': referenceId,
|
|
1045
|
+
'referenceAccount': referenceAccount,
|
|
1046
|
+
'type': type,
|
|
1047
|
+
'currency': code,
|
|
1048
|
+
'amount': this.parseNumber(amount),
|
|
1049
|
+
'before': undefined,
|
|
1050
|
+
'after': this.safeNumber(item, 'balance'),
|
|
1051
|
+
'status': 'ok',
|
|
1052
|
+
'timestamp': timestamp,
|
|
1053
|
+
'datetime': this.iso8601(timestamp),
|
|
1054
|
+
'fee': {
|
|
1055
|
+
'cost': this.safeNumber(item, 'fee'),
|
|
1056
|
+
'currency': code,
|
|
1057
|
+
},
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1061
|
+
/**
|
|
1062
|
+
* @method
|
|
1063
|
+
* @name kraken#fetchLedger
|
|
1064
|
+
* @description fetch the history of changes, actions done by the user or operations that altered balance of the user
|
|
1065
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getLedgers
|
|
1066
|
+
* @param {string} code unified currency code, default is undefined
|
|
1067
|
+
* @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
|
|
1068
|
+
* @param {int} [limit] max number of ledger entrys to return, default is undefined
|
|
1069
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1070
|
+
* @param {int} [params.until] timestamp in ms of the latest ledger entry
|
|
1071
|
+
* @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger-structure}
|
|
1072
|
+
*/
|
|
1073
|
+
// https://www.kraken.com/features/api#get-ledgers-info
|
|
1074
|
+
await this.loadMarkets();
|
|
1075
|
+
let request = {};
|
|
1076
|
+
let currency = undefined;
|
|
1077
|
+
if (code !== undefined) {
|
|
1078
|
+
currency = this.currency(code);
|
|
1079
|
+
request['asset'] = currency['id'];
|
|
1080
|
+
}
|
|
1081
|
+
if (since !== undefined) {
|
|
1082
|
+
request['start'] = this.parseToInt(since / 1000);
|
|
1083
|
+
}
|
|
1084
|
+
[request, params] = this.handleUntilOption('end', request, params);
|
|
1085
|
+
const response = await this.privatePostLedgers(this.extend(request, params));
|
|
1086
|
+
// { error: [],
|
|
1087
|
+
// "result": { ledger: { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N",
|
|
1088
|
+
// "time": 1520103488.314,
|
|
1089
|
+
// "type": "withdrawal",
|
|
1090
|
+
// "aclass": "currency",
|
|
1091
|
+
// "asset": "XETH",
|
|
1092
|
+
// "amount": "-0.2805800000",
|
|
1093
|
+
// "fee": "0.0050000000",
|
|
1094
|
+
// "balance": "0.0000051000" },
|
|
1095
|
+
const result = this.safeValue(response, 'result', {});
|
|
1096
|
+
const ledger = this.safeValue(result, 'ledger', {});
|
|
1097
|
+
const keys = Object.keys(ledger);
|
|
1098
|
+
const items = [];
|
|
1099
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1100
|
+
const key = keys[i];
|
|
1101
|
+
const value = ledger[key];
|
|
1102
|
+
value['id'] = key;
|
|
1103
|
+
items.push(value);
|
|
1104
|
+
}
|
|
1105
|
+
return this.parseLedger(items, currency, since, limit);
|
|
1106
|
+
}
|
|
1107
|
+
async fetchLedgerEntriesByIds(ids, code = undefined, params = {}) {
|
|
1108
|
+
// https://www.kraken.com/features/api#query-ledgers
|
|
1109
|
+
await this.loadMarkets();
|
|
1110
|
+
ids = ids.join(',');
|
|
1111
|
+
const request = this.extend({
|
|
1112
|
+
'id': ids,
|
|
1113
|
+
}, params);
|
|
1114
|
+
const response = await this.privatePostQueryLedgers(request);
|
|
1115
|
+
// { error: [],
|
|
1116
|
+
// "result": { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N",
|
|
1117
|
+
// "time": 1520103488.314,
|
|
1118
|
+
// "type": "withdrawal",
|
|
1119
|
+
// "aclass": "currency",
|
|
1120
|
+
// "asset": "XETH",
|
|
1121
|
+
// "amount": "-0.2805800000",
|
|
1122
|
+
// "fee": "0.0050000000",
|
|
1123
|
+
// "balance": "0.0000051000" } } }
|
|
1124
|
+
const result = response['result'];
|
|
1125
|
+
const keys = Object.keys(result);
|
|
1126
|
+
const items = [];
|
|
1127
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1128
|
+
const key = keys[i];
|
|
1129
|
+
const value = result[key];
|
|
1130
|
+
value['id'] = key;
|
|
1131
|
+
items.push(value);
|
|
1132
|
+
}
|
|
1133
|
+
return this.parseLedger(items);
|
|
1134
|
+
}
|
|
1135
|
+
async fetchLedgerEntry(id, code = undefined, params = {}) {
|
|
1136
|
+
const items = await this.fetchLedgerEntriesByIds([id], code, params);
|
|
1137
|
+
return items[0];
|
|
1138
|
+
}
|
|
1139
|
+
parseTrade(trade, market = undefined) {
|
|
1140
|
+
//
|
|
1141
|
+
// fetchTrades (public)
|
|
1142
|
+
//
|
|
1143
|
+
// [
|
|
1144
|
+
// "0.032310", // price
|
|
1145
|
+
// "4.28169434", // amount
|
|
1146
|
+
// 1541390792.763, // timestamp
|
|
1147
|
+
// "s", // sell or buy
|
|
1148
|
+
// "l", // limit or market
|
|
1149
|
+
// ""
|
|
1150
|
+
// ]
|
|
1151
|
+
//
|
|
1152
|
+
// fetchOrderTrades (private)
|
|
1153
|
+
//
|
|
1154
|
+
// {
|
|
1155
|
+
// "id": 'TIMIRG-WUNNE-RRJ6GT', // injected from outside
|
|
1156
|
+
// "ordertxid": 'OQRPN2-LRHFY-HIFA7D',
|
|
1157
|
+
// "postxid": 'TKH2SE-M7IF5-CFI7LT',
|
|
1158
|
+
// "pair": 'USDCUSDT',
|
|
1159
|
+
// "time": 1586340086.457,
|
|
1160
|
+
// "type": 'sell',
|
|
1161
|
+
// "ordertype": 'market',
|
|
1162
|
+
// "price": '0.99860000',
|
|
1163
|
+
// "cost": '22.16892001',
|
|
1164
|
+
// "fee": '0.04433784',
|
|
1165
|
+
// "vol": '22.20000000',
|
|
1166
|
+
// "margin": '0.00000000',
|
|
1167
|
+
// "misc": ''
|
|
1168
|
+
// }
|
|
1169
|
+
//
|
|
1170
|
+
let timestamp = undefined;
|
|
1171
|
+
let side = undefined;
|
|
1172
|
+
let type = undefined;
|
|
1173
|
+
let price = undefined;
|
|
1174
|
+
let amount = undefined;
|
|
1175
|
+
let id = undefined;
|
|
1176
|
+
let orderId = undefined;
|
|
1177
|
+
let fee = undefined;
|
|
1178
|
+
let symbol = undefined;
|
|
1179
|
+
if (Array.isArray(trade)) {
|
|
1180
|
+
timestamp = this.safeTimestamp(trade, 2);
|
|
1181
|
+
side = (trade[3] === 's') ? 'sell' : 'buy';
|
|
1182
|
+
type = (trade[4] === 'l') ? 'limit' : 'market';
|
|
1183
|
+
price = this.safeString(trade, 0);
|
|
1184
|
+
amount = this.safeString(trade, 1);
|
|
1185
|
+
const tradeLength = trade.length;
|
|
1186
|
+
if (tradeLength > 6) {
|
|
1187
|
+
id = this.safeString(trade, 6); // artificially added as per #1794
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
else if (typeof trade === 'string') {
|
|
1191
|
+
id = trade;
|
|
1192
|
+
}
|
|
1193
|
+
else if ('ordertxid' in trade) {
|
|
1194
|
+
const marketId = this.safeString(trade, 'pair');
|
|
1195
|
+
const foundMarket = this.findMarketByAltnameOrId(marketId);
|
|
1196
|
+
if (foundMarket !== undefined) {
|
|
1197
|
+
market = foundMarket;
|
|
1198
|
+
}
|
|
1199
|
+
else if (marketId !== undefined) {
|
|
1200
|
+
// delisted market ids go here
|
|
1201
|
+
market = this.getDelistedMarketById(marketId);
|
|
1202
|
+
}
|
|
1203
|
+
orderId = this.safeString(trade, 'ordertxid');
|
|
1204
|
+
id = this.safeString2(trade, 'id', 'postxid');
|
|
1205
|
+
timestamp = this.safeTimestamp(trade, 'time');
|
|
1206
|
+
side = this.safeString(trade, 'type');
|
|
1207
|
+
type = this.safeString(trade, 'ordertype');
|
|
1208
|
+
price = this.safeString(trade, 'price');
|
|
1209
|
+
amount = this.safeString(trade, 'vol');
|
|
1210
|
+
if ('fee' in trade) {
|
|
1211
|
+
let currency = undefined;
|
|
1212
|
+
if (market !== undefined) {
|
|
1213
|
+
currency = market['quote'];
|
|
1214
|
+
}
|
|
1215
|
+
fee = {
|
|
1216
|
+
'cost': this.safeString(trade, 'fee'),
|
|
1217
|
+
'currency': currency,
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
if (market !== undefined) {
|
|
1222
|
+
symbol = market['symbol'];
|
|
1223
|
+
}
|
|
1224
|
+
const cost = this.safeString(trade, 'cost');
|
|
1225
|
+
return this.safeTrade({
|
|
1226
|
+
'id': id,
|
|
1227
|
+
'order': orderId,
|
|
1228
|
+
'info': trade,
|
|
1229
|
+
'timestamp': timestamp,
|
|
1230
|
+
'datetime': this.iso8601(timestamp),
|
|
1231
|
+
'symbol': symbol,
|
|
1232
|
+
'type': type,
|
|
1233
|
+
'side': side,
|
|
1234
|
+
'takerOrMaker': undefined,
|
|
1235
|
+
'price': price,
|
|
1236
|
+
'amount': amount,
|
|
1237
|
+
'cost': cost,
|
|
1238
|
+
'fee': fee,
|
|
1239
|
+
}, market);
|
|
1240
|
+
}
|
|
1241
|
+
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
1242
|
+
/**
|
|
1243
|
+
* @method
|
|
1244
|
+
* @name kraken#fetchTrades
|
|
1245
|
+
* @description get the list of most recent trades for a particular symbol
|
|
1246
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getRecentTrades
|
|
1247
|
+
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
1248
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
1249
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
1250
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1251
|
+
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
1252
|
+
*/
|
|
1253
|
+
await this.loadMarkets();
|
|
1254
|
+
const market = this.market(symbol);
|
|
1255
|
+
const id = market['id'];
|
|
1256
|
+
const request = {
|
|
1257
|
+
'pair': id,
|
|
1258
|
+
};
|
|
1259
|
+
// https://support.kraken.com/hc/en-us/articles/218198197-How-to-pull-all-trade-data-using-the-Kraken-REST-API
|
|
1260
|
+
// https://github.com/ccxt/ccxt/issues/5677
|
|
1261
|
+
if (since !== undefined) {
|
|
1262
|
+
// php does not format it properly
|
|
1263
|
+
// therefore we use string concatenation here
|
|
1264
|
+
request['since'] = since * 1e6;
|
|
1265
|
+
request['since'] = since.toString() + '000000'; // expected to be in nanoseconds
|
|
1266
|
+
}
|
|
1267
|
+
// https://github.com/ccxt/ccxt/issues/5698
|
|
1268
|
+
if (limit !== undefined && limit !== 1000) {
|
|
1269
|
+
const fetchTradesWarning = this.safeValue(this.options, 'fetchTradesWarning', true);
|
|
1270
|
+
if (fetchTradesWarning) {
|
|
1271
|
+
throw new errors.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.");
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
const response = await this.publicGetTrades(this.extend(request, params));
|
|
1275
|
+
//
|
|
1276
|
+
// {
|
|
1277
|
+
// "error": [],
|
|
1278
|
+
// "result": {
|
|
1279
|
+
// "XETHXXBT": [
|
|
1280
|
+
// ["0.032310","4.28169434",1541390792.763,"s","l",""]
|
|
1281
|
+
// ],
|
|
1282
|
+
// "last": "1541439421200678657"
|
|
1283
|
+
// }
|
|
1284
|
+
// }
|
|
1285
|
+
//
|
|
1286
|
+
const result = response['result'];
|
|
1287
|
+
const trades = result[id];
|
|
1288
|
+
// trades is a sorted array: last (most recent trade) goes last
|
|
1289
|
+
const length = trades.length;
|
|
1290
|
+
if (length <= 0) {
|
|
1291
|
+
return [];
|
|
1292
|
+
}
|
|
1293
|
+
const lastTrade = trades[length - 1];
|
|
1294
|
+
const lastTradeId = this.safeString(result, 'last');
|
|
1295
|
+
lastTrade.push(lastTradeId);
|
|
1296
|
+
return this.parseTrades(trades, market, since, limit);
|
|
1297
|
+
}
|
|
1298
|
+
parseBalance(response) {
|
|
1299
|
+
const balances = this.safeValue(response, 'result', {});
|
|
1300
|
+
const result = {
|
|
1301
|
+
'info': response,
|
|
1302
|
+
'timestamp': undefined,
|
|
1303
|
+
'datetime': undefined,
|
|
1304
|
+
};
|
|
1305
|
+
const currencyIds = Object.keys(balances);
|
|
1306
|
+
for (let i = 0; i < currencyIds.length; i++) {
|
|
1307
|
+
const currencyId = currencyIds[i];
|
|
1308
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
1309
|
+
const balance = this.safeValue(balances, currencyId, {});
|
|
1310
|
+
const account = this.account();
|
|
1311
|
+
account['used'] = this.safeString(balance, 'hold_trade');
|
|
1312
|
+
account['total'] = this.safeString(balance, 'balance');
|
|
1313
|
+
result[code] = account;
|
|
1314
|
+
}
|
|
1315
|
+
return this.safeBalance(result);
|
|
1316
|
+
}
|
|
1317
|
+
async fetchBalance(params = {}) {
|
|
1318
|
+
/**
|
|
1319
|
+
* @method
|
|
1320
|
+
* @name kraken#fetchBalance
|
|
1321
|
+
* @description query for balance and get the amount of funds available for trading or funds locked in orders
|
|
1322
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getExtendedBalance
|
|
1323
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1324
|
+
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
1325
|
+
*/
|
|
1326
|
+
await this.loadMarkets();
|
|
1327
|
+
const response = await this.privatePostBalanceEx(params);
|
|
1328
|
+
//
|
|
1329
|
+
// {
|
|
1330
|
+
// "error": [],
|
|
1331
|
+
// "result": {
|
|
1332
|
+
// "ZUSD": {
|
|
1333
|
+
// "balance": 25435.21,
|
|
1334
|
+
// "hold_trade": 8249.76
|
|
1335
|
+
// },
|
|
1336
|
+
// "XXBT": {
|
|
1337
|
+
// "balance": 1.2435,
|
|
1338
|
+
// "hold_trade": 0.8423
|
|
1339
|
+
// }
|
|
1340
|
+
// }
|
|
1341
|
+
// }
|
|
1342
|
+
//
|
|
1343
|
+
return this.parseBalance(response);
|
|
1344
|
+
}
|
|
1345
|
+
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
|
|
1346
|
+
/**
|
|
1347
|
+
* @method
|
|
1348
|
+
* @name kraken#createOrder
|
|
1349
|
+
* @see https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
|
|
1350
|
+
* @description create a trade order
|
|
1351
|
+
* @param {string} symbol unified symbol of the market to create an order in
|
|
1352
|
+
* @param {string} type 'market' or 'limit'
|
|
1353
|
+
* @param {string} side 'buy' or 'sell'
|
|
1354
|
+
* @param {float} amount how much of currency you want to trade in units of base currency
|
|
1355
|
+
* @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
1356
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1357
|
+
* @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
|
|
1358
|
+
* @param {bool} [params.reduceOnly] *margin only* indicates if this order is to reduce the size of a position
|
|
1359
|
+
* @param {float} [params.stopLossPrice] *margin only* the price that a stop loss order is triggered at
|
|
1360
|
+
* @param {float} [params.takeProfitPrice] *margin only* the price that a take profit order is triggered at
|
|
1361
|
+
* @param {string} [params.trailingAmount] *margin only* the quote amount to trail away from the current market price
|
|
1362
|
+
* @param {string} [params.trailingLimitAmount] *margin only* the quote amount away from the trailingAmount
|
|
1363
|
+
* @param {string} [params.offset] *margin only* '+' or '-' whether you want the trailingLimitAmount value to be positive or negative, default is negative '-'
|
|
1364
|
+
* @param {string} [params.trigger] *margin only* the activation price type, 'last' or 'index', default is 'last'
|
|
1365
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1366
|
+
*/
|
|
1367
|
+
await this.loadMarkets();
|
|
1368
|
+
const market = this.market(symbol);
|
|
1369
|
+
const request = {
|
|
1370
|
+
'pair': market['id'],
|
|
1371
|
+
'type': side,
|
|
1372
|
+
'ordertype': type,
|
|
1373
|
+
'volume': this.amountToPrecision(symbol, amount),
|
|
1374
|
+
};
|
|
1375
|
+
const orderRequest = this.orderRequest('createOrder()', symbol, type, request, price, params);
|
|
1376
|
+
const response = await this.privatePostAddOrder(this.extend(orderRequest[0], orderRequest[1]));
|
|
1377
|
+
//
|
|
1378
|
+
// {
|
|
1379
|
+
// "error": [],
|
|
1380
|
+
// "result": {
|
|
1381
|
+
// "descr": { order: 'buy 0.02100000 ETHUSDT @ limit 330.00' },
|
|
1382
|
+
// "txid": [ 'OEKVV2-IH52O-TPL6GZ' ]
|
|
1383
|
+
// }
|
|
1384
|
+
// }
|
|
1385
|
+
//
|
|
1386
|
+
const result = this.safeValue(response, 'result');
|
|
1387
|
+
return this.parseOrder(result);
|
|
1388
|
+
}
|
|
1389
|
+
findMarketByAltnameOrId(id) {
|
|
1390
|
+
const marketsByAltname = this.safeValue(this.options, 'marketsByAltname', {});
|
|
1391
|
+
if (id in marketsByAltname) {
|
|
1392
|
+
return marketsByAltname[id];
|
|
1393
|
+
}
|
|
1394
|
+
else {
|
|
1395
|
+
return this.safeMarket(id);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
getDelistedMarketById(id) {
|
|
1399
|
+
if (id === undefined) {
|
|
1400
|
+
return id;
|
|
1401
|
+
}
|
|
1402
|
+
let market = this.safeValue(this.options['delistedMarketsById'], id);
|
|
1403
|
+
if (market !== undefined) {
|
|
1404
|
+
return market;
|
|
1405
|
+
}
|
|
1406
|
+
const baseIdStart = 0;
|
|
1407
|
+
let baseIdEnd = 3;
|
|
1408
|
+
let quoteIdStart = 3;
|
|
1409
|
+
let quoteIdEnd = 6;
|
|
1410
|
+
if (id.length === 8) {
|
|
1411
|
+
baseIdEnd = 4;
|
|
1412
|
+
quoteIdStart = 4;
|
|
1413
|
+
quoteIdEnd = 8;
|
|
1414
|
+
}
|
|
1415
|
+
else if (id.length === 7) {
|
|
1416
|
+
baseIdEnd = 4;
|
|
1417
|
+
quoteIdStart = 4;
|
|
1418
|
+
quoteIdEnd = 7;
|
|
1419
|
+
}
|
|
1420
|
+
const baseId = id.slice(baseIdStart, baseIdEnd);
|
|
1421
|
+
const quoteId = id.slice(quoteIdStart, quoteIdEnd);
|
|
1422
|
+
const base = this.safeCurrencyCode(baseId);
|
|
1423
|
+
const quote = this.safeCurrencyCode(quoteId);
|
|
1424
|
+
const symbol = base + '/' + quote;
|
|
1425
|
+
market = {
|
|
1426
|
+
'symbol': symbol,
|
|
1427
|
+
'base': base,
|
|
1428
|
+
'quote': quote,
|
|
1429
|
+
'baseId': baseId,
|
|
1430
|
+
'quoteId': quoteId,
|
|
1431
|
+
};
|
|
1432
|
+
this.options['delistedMarketsById'][id] = market;
|
|
1433
|
+
return market;
|
|
1434
|
+
}
|
|
1435
|
+
parseOrderStatus(status) {
|
|
1436
|
+
const statuses = {
|
|
1437
|
+
'pending': 'open',
|
|
1438
|
+
'open': 'open',
|
|
1439
|
+
'closed': 'closed',
|
|
1440
|
+
'canceled': 'canceled',
|
|
1441
|
+
'expired': 'expired',
|
|
1442
|
+
};
|
|
1443
|
+
return this.safeString(statuses, status, status);
|
|
1444
|
+
}
|
|
1445
|
+
parseOrder(order, market = undefined) {
|
|
1446
|
+
//
|
|
1447
|
+
// createOrder for regular orders
|
|
1448
|
+
//
|
|
1449
|
+
// {
|
|
1450
|
+
// "descr": { order: 'buy 0.02100000 ETHUSDT @ limit 330.00' },
|
|
1451
|
+
// "txid": [ 'OEKVV2-IH52O-TPL6GZ' ]
|
|
1452
|
+
// }
|
|
1453
|
+
// {
|
|
1454
|
+
// "txid": [ "TX_ID_HERE" ],
|
|
1455
|
+
// "descr": { "order":"buy 0.12345678 ETHEUR @ market" },
|
|
1456
|
+
// }
|
|
1457
|
+
//
|
|
1458
|
+
//
|
|
1459
|
+
// createOrder for stop orders
|
|
1460
|
+
//
|
|
1461
|
+
// {
|
|
1462
|
+
// "txid":["OSILNC-VQI5Q-775ZDQ"],
|
|
1463
|
+
// "descr":{"order":"sell 167.28002676 ADAXBT @ stop loss 0.00003280 -> limit 0.00003212"}
|
|
1464
|
+
// }
|
|
1465
|
+
//
|
|
1466
|
+
//
|
|
1467
|
+
// {
|
|
1468
|
+
// "txid":["OVHMJV-BZW2V-6NZFWF"],
|
|
1469
|
+
// "descr":{"order":"sell 0.00100000 ETHUSD @ stop loss 2677.00 -> limit 2577.00 with 5:1 leverage"}
|
|
1470
|
+
// }
|
|
1471
|
+
//
|
|
1472
|
+
// editOrder
|
|
1473
|
+
//
|
|
1474
|
+
// {
|
|
1475
|
+
// "status": "ok",
|
|
1476
|
+
// "txid": "OAW2BO-7RWEK-PZY5UO",
|
|
1477
|
+
// "originaltxid": "OXL6SS-UPNMC-26WBE7",
|
|
1478
|
+
// "volume": "0.00075000",
|
|
1479
|
+
// "price": "13500.0",
|
|
1480
|
+
// "orders_cancelled": 1,
|
|
1481
|
+
// "descr": {
|
|
1482
|
+
// "order": "buy 0.00075000 XBTUSDT @ limit 13500.0"
|
|
1483
|
+
// }
|
|
1484
|
+
// }
|
|
1485
|
+
// ws - createOrder
|
|
1486
|
+
// {
|
|
1487
|
+
// "descr": 'sell 0.00010000 XBTUSDT @ market',
|
|
1488
|
+
// "event": 'addOrderStatus',
|
|
1489
|
+
// "reqid": 1,
|
|
1490
|
+
// "status": 'ok',
|
|
1491
|
+
// "txid": 'OAVXZH-XIE54-JCYYDG'
|
|
1492
|
+
// }
|
|
1493
|
+
// ws - editOrder
|
|
1494
|
+
// {
|
|
1495
|
+
// "descr": "order edited price = 9000.00000000",
|
|
1496
|
+
// "event": "editOrderStatus",
|
|
1497
|
+
// "originaltxid": "O65KZW-J4AW3-VFS74A",
|
|
1498
|
+
// "reqid": 3,
|
|
1499
|
+
// "status": "ok",
|
|
1500
|
+
// "txid": "OTI672-HJFAO-XOIPPK"
|
|
1501
|
+
// }
|
|
1502
|
+
//
|
|
1503
|
+
const description = this.safeValue(order, 'descr', {});
|
|
1504
|
+
const orderDescription = this.safeString(description, 'order', description);
|
|
1505
|
+
let side = undefined;
|
|
1506
|
+
let type = undefined;
|
|
1507
|
+
let marketId = undefined;
|
|
1508
|
+
let price = undefined;
|
|
1509
|
+
let amount = undefined;
|
|
1510
|
+
let stopPrice = undefined;
|
|
1511
|
+
if (orderDescription !== undefined) {
|
|
1512
|
+
const parts = orderDescription.split(' ');
|
|
1513
|
+
side = this.safeString(parts, 0);
|
|
1514
|
+
amount = this.safeString(parts, 1);
|
|
1515
|
+
marketId = this.safeString(parts, 2);
|
|
1516
|
+
type = this.safeString(parts, 4);
|
|
1517
|
+
if (type === 'stop') {
|
|
1518
|
+
stopPrice = this.safeString(parts, 6);
|
|
1519
|
+
price = this.safeString(parts, 9);
|
|
1520
|
+
}
|
|
1521
|
+
else if (type === 'limit') {
|
|
1522
|
+
price = this.safeString(parts, 5);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
side = this.safeString(description, 'type', side);
|
|
1526
|
+
type = this.safeString(description, 'ordertype', type);
|
|
1527
|
+
marketId = this.safeString(description, 'pair', marketId);
|
|
1528
|
+
const foundMarket = this.findMarketByAltnameOrId(marketId);
|
|
1529
|
+
let symbol = undefined;
|
|
1530
|
+
if (foundMarket !== undefined) {
|
|
1531
|
+
market = foundMarket;
|
|
1532
|
+
}
|
|
1533
|
+
else if (marketId !== undefined) {
|
|
1534
|
+
// delisted market ids go here
|
|
1535
|
+
market = this.getDelistedMarketById(marketId);
|
|
1536
|
+
}
|
|
1537
|
+
const timestamp = this.safeTimestamp(order, 'opentm');
|
|
1538
|
+
amount = this.safeString(order, 'vol', amount);
|
|
1539
|
+
const filled = this.safeString(order, 'vol_exec');
|
|
1540
|
+
let fee = undefined;
|
|
1541
|
+
// kraken truncates the cost in the api response so we will ignore it and calculate it from average & filled
|
|
1542
|
+
// const cost = this.safeString (order, 'cost');
|
|
1543
|
+
price = this.safeString(description, 'price', price);
|
|
1544
|
+
if ((price === undefined) || Precise["default"].stringEquals(price, '0')) {
|
|
1545
|
+
price = this.safeString(description, 'price2');
|
|
1546
|
+
}
|
|
1547
|
+
if ((price === undefined) || Precise["default"].stringEquals(price, '0')) {
|
|
1548
|
+
price = this.safeString(order, 'price', price);
|
|
1549
|
+
}
|
|
1550
|
+
const flags = this.safeString(order, 'oflags', '');
|
|
1551
|
+
const isPostOnly = flags.indexOf('post') > -1;
|
|
1552
|
+
const average = this.safeNumber(order, 'price');
|
|
1553
|
+
if (market !== undefined) {
|
|
1554
|
+
symbol = market['symbol'];
|
|
1555
|
+
if ('fee' in order) {
|
|
1556
|
+
const feeCost = this.safeString(order, 'fee');
|
|
1557
|
+
fee = {
|
|
1558
|
+
'cost': feeCost,
|
|
1559
|
+
'rate': undefined,
|
|
1560
|
+
};
|
|
1561
|
+
if (flags.indexOf('fciq') >= 0) {
|
|
1562
|
+
fee['currency'] = market['quote'];
|
|
1563
|
+
}
|
|
1564
|
+
else if (flags.indexOf('fcib') >= 0) {
|
|
1565
|
+
fee['currency'] = market['base'];
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
const status = this.parseOrderStatus(this.safeString(order, 'status'));
|
|
1570
|
+
let id = this.safeString2(order, 'id', 'txid');
|
|
1571
|
+
if ((id === undefined) || (id.slice(0, 1) === '[')) {
|
|
1572
|
+
const txid = this.safeValue(order, 'txid');
|
|
1573
|
+
id = this.safeString(txid, 0);
|
|
1574
|
+
}
|
|
1575
|
+
const clientOrderId = this.safeString(order, 'userref');
|
|
1576
|
+
const rawTrades = this.safeValue(order, 'trades', []);
|
|
1577
|
+
const trades = [];
|
|
1578
|
+
for (let i = 0; i < rawTrades.length; i++) {
|
|
1579
|
+
const rawTrade = rawTrades[i];
|
|
1580
|
+
if (typeof rawTrade === 'string') {
|
|
1581
|
+
trades.push(this.safeTrade({ 'id': rawTrade, 'orderId': id, 'symbol': symbol, 'info': {} }));
|
|
1582
|
+
}
|
|
1583
|
+
else {
|
|
1584
|
+
trades.push(rawTrade);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
stopPrice = this.safeNumber(order, 'stopprice', stopPrice);
|
|
1588
|
+
return this.safeOrder({
|
|
1589
|
+
'id': id,
|
|
1590
|
+
'clientOrderId': clientOrderId,
|
|
1591
|
+
'info': order,
|
|
1592
|
+
'timestamp': timestamp,
|
|
1593
|
+
'datetime': this.iso8601(timestamp),
|
|
1594
|
+
'lastTradeTimestamp': undefined,
|
|
1595
|
+
'status': status,
|
|
1596
|
+
'symbol': symbol,
|
|
1597
|
+
'type': type,
|
|
1598
|
+
'timeInForce': undefined,
|
|
1599
|
+
'postOnly': isPostOnly,
|
|
1600
|
+
'side': side,
|
|
1601
|
+
'price': price,
|
|
1602
|
+
'stopPrice': stopPrice,
|
|
1603
|
+
'triggerPrice': stopPrice,
|
|
1604
|
+
'cost': undefined,
|
|
1605
|
+
'amount': amount,
|
|
1606
|
+
'filled': filled,
|
|
1607
|
+
'average': average,
|
|
1608
|
+
'remaining': undefined,
|
|
1609
|
+
'fee': fee,
|
|
1610
|
+
'trades': trades,
|
|
1611
|
+
}, market);
|
|
1612
|
+
}
|
|
1613
|
+
orderRequest(method, symbol, type, request, price = undefined, params = {}) {
|
|
1614
|
+
const clientOrderId = this.safeString2(params, 'userref', 'clientOrderId');
|
|
1615
|
+
params = this.omit(params, ['userref', 'clientOrderId']);
|
|
1616
|
+
if (clientOrderId !== undefined) {
|
|
1617
|
+
request['userref'] = clientOrderId;
|
|
1618
|
+
}
|
|
1619
|
+
const stopLossTriggerPrice = this.safeString(params, 'stopLossPrice');
|
|
1620
|
+
const takeProfitTriggerPrice = this.safeString(params, 'takeProfitPrice');
|
|
1621
|
+
const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
|
|
1622
|
+
const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
|
|
1623
|
+
const isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder || isTakeProfitTriggerOrder;
|
|
1624
|
+
const trailingAmount = this.safeString(params, 'trailingAmount');
|
|
1625
|
+
const trailingLimitAmount = this.safeString(params, 'trailingLimitAmount');
|
|
1626
|
+
const isTrailingAmountOrder = trailingAmount !== undefined;
|
|
1627
|
+
if ((type === 'limit') && !isTrailingAmountOrder) {
|
|
1628
|
+
request['price'] = this.priceToPrecision(symbol, price);
|
|
1629
|
+
}
|
|
1630
|
+
let reduceOnly = this.safeValue2(params, 'reduceOnly', 'reduce_only');
|
|
1631
|
+
if (isStopLossOrTakeProfitTrigger) {
|
|
1632
|
+
if (isStopLossTriggerOrder) {
|
|
1633
|
+
request['price'] = this.priceToPrecision(symbol, stopLossTriggerPrice);
|
|
1634
|
+
request['ordertype'] = 'stop-loss-limit';
|
|
1635
|
+
}
|
|
1636
|
+
else if (isTakeProfitTriggerOrder) {
|
|
1637
|
+
request['price'] = this.priceToPrecision(symbol, takeProfitTriggerPrice);
|
|
1638
|
+
request['ordertype'] = 'take-profit-limit';
|
|
1639
|
+
}
|
|
1640
|
+
request['price2'] = this.priceToPrecision(symbol, price);
|
|
1641
|
+
reduceOnly = true;
|
|
1642
|
+
}
|
|
1643
|
+
else if (isTrailingAmountOrder) {
|
|
1644
|
+
const trailingActivationPriceType = this.safeString(params, 'trigger', 'last');
|
|
1645
|
+
const trailingAmountString = '+' + trailingAmount;
|
|
1646
|
+
request['trigger'] = trailingActivationPriceType;
|
|
1647
|
+
if ((type === 'limit') || (trailingLimitAmount !== undefined)) {
|
|
1648
|
+
const offset = this.safeString(params, 'offset', '-');
|
|
1649
|
+
const trailingLimitAmountString = offset + this.numberToString(trailingLimitAmount);
|
|
1650
|
+
request['price'] = trailingAmountString;
|
|
1651
|
+
request['price2'] = trailingLimitAmountString;
|
|
1652
|
+
request['ordertype'] = 'trailing-stop-limit';
|
|
1653
|
+
}
|
|
1654
|
+
else {
|
|
1655
|
+
request['price'] = trailingAmountString;
|
|
1656
|
+
request['ordertype'] = 'trailing-stop';
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
if (reduceOnly) {
|
|
1660
|
+
request['reduce_only'] = 'true'; // not using boolean in this case, because the urlencodedNested transforms it into 'True' string
|
|
1661
|
+
}
|
|
1662
|
+
let close = this.safeValue(params, 'close');
|
|
1663
|
+
if (close !== undefined) {
|
|
1664
|
+
close = this.extend({}, close);
|
|
1665
|
+
const closePrice = this.safeValue(close, 'price');
|
|
1666
|
+
if (closePrice !== undefined) {
|
|
1667
|
+
close['price'] = this.priceToPrecision(symbol, closePrice);
|
|
1668
|
+
}
|
|
1669
|
+
const closePrice2 = this.safeValue(close, 'price2'); // stopPrice
|
|
1670
|
+
if (closePrice2 !== undefined) {
|
|
1671
|
+
close['price2'] = this.priceToPrecision(symbol, closePrice2);
|
|
1672
|
+
}
|
|
1673
|
+
request['close'] = close;
|
|
1674
|
+
}
|
|
1675
|
+
const timeInForce = this.safeString2(params, 'timeInForce', 'timeinforce');
|
|
1676
|
+
if (timeInForce !== undefined) {
|
|
1677
|
+
request['timeinforce'] = timeInForce;
|
|
1678
|
+
}
|
|
1679
|
+
const isMarket = (type === 'market');
|
|
1680
|
+
let postOnly = undefined;
|
|
1681
|
+
[postOnly, params] = this.handlePostOnly(isMarket, false, params);
|
|
1682
|
+
if (postOnly) {
|
|
1683
|
+
request['oflags'] = 'post';
|
|
1684
|
+
}
|
|
1685
|
+
params = this.omit(params, ['timeInForce', 'reduceOnly', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingLimitAmount', 'offset']);
|
|
1686
|
+
return [request, params];
|
|
1687
|
+
}
|
|
1688
|
+
async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
|
|
1689
|
+
/**
|
|
1690
|
+
* @method
|
|
1691
|
+
* @name kraken#editOrder
|
|
1692
|
+
* @description edit a trade order
|
|
1693
|
+
* @see https://docs.kraken.com/rest/#tag/Trading/operation/editOrder
|
|
1694
|
+
* @param {string} id order id
|
|
1695
|
+
* @param {string} symbol unified symbol of the market to create an order in
|
|
1696
|
+
* @param {string} type 'market' or 'limit'
|
|
1697
|
+
* @param {string} side 'buy' or 'sell'
|
|
1698
|
+
* @param {float} amount how much of the currency you want to trade in units of the base currency
|
|
1699
|
+
* @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
1700
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1701
|
+
* @param {float} [params.stopLossPrice] *margin only* the price that a stop loss order is triggered at
|
|
1702
|
+
* @param {float} [params.takeProfitPrice] *margin only* the price that a take profit order is triggered at
|
|
1703
|
+
* @param {string} [params.trailingAmount] *margin only* the quote price away from the current market price
|
|
1704
|
+
* @param {string} [params.trailingLimitAmount] *margin only* the quote amount away from the trailingAmount
|
|
1705
|
+
* @param {string} [params.offset] *margin only* '+' or '-' whether you want the trailingLimitAmount value to be positive or negative, default is negative '-'
|
|
1706
|
+
* @param {string} [params.trigger] *margin only* the activation price type, 'last' or 'index', default is 'last'
|
|
1707
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1708
|
+
*/
|
|
1709
|
+
await this.loadMarkets();
|
|
1710
|
+
const market = this.market(symbol);
|
|
1711
|
+
if (!market['spot']) {
|
|
1712
|
+
throw new errors.NotSupported(this.id + ' editOrder() does not support ' + market['type'] + ' orders, only spot orders are accepted');
|
|
1713
|
+
}
|
|
1714
|
+
const request = {
|
|
1715
|
+
'txid': id,
|
|
1716
|
+
'pair': market['id'],
|
|
1717
|
+
};
|
|
1718
|
+
if (amount !== undefined) {
|
|
1719
|
+
request['volume'] = this.amountToPrecision(symbol, amount);
|
|
1720
|
+
}
|
|
1721
|
+
const orderRequest = this.orderRequest('editOrder()', symbol, type, request, price, params);
|
|
1722
|
+
const response = await this.privatePostEditOrder(this.extend(orderRequest[0], orderRequest[1]));
|
|
1723
|
+
//
|
|
1724
|
+
// {
|
|
1725
|
+
// "error": [],
|
|
1726
|
+
// "result": {
|
|
1727
|
+
// "status": "ok",
|
|
1728
|
+
// "txid": "OAW2BO-7RWEK-PZY5UO",
|
|
1729
|
+
// "originaltxid": "OXL6SS-UPNMC-26WBE7",
|
|
1730
|
+
// "volume": "0.00075000",
|
|
1731
|
+
// "price": "13500.0",
|
|
1732
|
+
// "orders_cancelled": 1,
|
|
1733
|
+
// "descr": {
|
|
1734
|
+
// "order": "buy 0.00075000 XBTUSDT @ limit 13500.0"
|
|
1735
|
+
// }
|
|
1736
|
+
// }
|
|
1737
|
+
// }
|
|
1738
|
+
//
|
|
1739
|
+
const data = this.safeValue(response, 'result', {});
|
|
1740
|
+
return this.parseOrder(data, market);
|
|
1741
|
+
}
|
|
1742
|
+
async fetchOrder(id, symbol = undefined, params = {}) {
|
|
1743
|
+
/**
|
|
1744
|
+
* @method
|
|
1745
|
+
* @name kraken#fetchOrder
|
|
1746
|
+
* @description fetches information on an order made by the user
|
|
1747
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getOrdersInfo
|
|
1748
|
+
* @param {string} symbol not used by kraken fetchOrder
|
|
1749
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1750
|
+
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1751
|
+
*/
|
|
1752
|
+
await this.loadMarkets();
|
|
1753
|
+
const clientOrderId = this.safeValue2(params, 'userref', 'clientOrderId');
|
|
1754
|
+
const request = {
|
|
1755
|
+
'trades': true, // whether or not to include trades in output (optional, default false)
|
|
1756
|
+
// 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
|
|
1757
|
+
// 'userref': 'optional', // restrict results to given user reference id (optional)
|
|
1758
|
+
};
|
|
1759
|
+
let query = params;
|
|
1760
|
+
if (clientOrderId !== undefined) {
|
|
1761
|
+
request['userref'] = clientOrderId;
|
|
1762
|
+
query = this.omit(params, ['userref', 'clientOrderId']);
|
|
1763
|
+
}
|
|
1764
|
+
else {
|
|
1765
|
+
request['txid'] = id;
|
|
1766
|
+
}
|
|
1767
|
+
const response = await this.privatePostQueryOrders(this.extend(request, query));
|
|
1768
|
+
//
|
|
1769
|
+
// {
|
|
1770
|
+
// "error":[],
|
|
1771
|
+
// "result":{
|
|
1772
|
+
// "OTLAS3-RRHUF-NDWH5A":{
|
|
1773
|
+
// "refid":null,
|
|
1774
|
+
// "userref":null,
|
|
1775
|
+
// "status":"closed",
|
|
1776
|
+
// "reason":null,
|
|
1777
|
+
// "opentm":1586822919.3342,
|
|
1778
|
+
// "closetm":1586822919.365,
|
|
1779
|
+
// "starttm":0,
|
|
1780
|
+
// "expiretm":0,
|
|
1781
|
+
// "descr":{
|
|
1782
|
+
// "pair":"XBTUSDT",
|
|
1783
|
+
// "type":"sell",
|
|
1784
|
+
// "ordertype":"market",
|
|
1785
|
+
// "price":"0",
|
|
1786
|
+
// "price2":"0",
|
|
1787
|
+
// "leverage":"none",
|
|
1788
|
+
// "order":"sell 0.21804000 XBTUSDT @ market",
|
|
1789
|
+
// "close":""
|
|
1790
|
+
// },
|
|
1791
|
+
// "vol":"0.21804000",
|
|
1792
|
+
// "vol_exec":"0.21804000",
|
|
1793
|
+
// "cost":"1493.9",
|
|
1794
|
+
// "fee":"3.8",
|
|
1795
|
+
// "price":"6851.5",
|
|
1796
|
+
// "stopprice":"0.00000",
|
|
1797
|
+
// "limitprice":"0.00000",
|
|
1798
|
+
// "misc":"",
|
|
1799
|
+
// "oflags":"fciq",
|
|
1800
|
+
// "trades":["TT5UC3-GOIRW-6AZZ6R"]
|
|
1801
|
+
// }
|
|
1802
|
+
// }
|
|
1803
|
+
// }
|
|
1804
|
+
//
|
|
1805
|
+
const result = this.safeValue(response, 'result', []);
|
|
1806
|
+
if (!(id in result)) {
|
|
1807
|
+
throw new errors.OrderNotFound(this.id + ' fetchOrder() could not find order id ' + id);
|
|
1808
|
+
}
|
|
1809
|
+
return this.parseOrder(this.extend({ 'id': id }, result[id]));
|
|
1810
|
+
}
|
|
1811
|
+
async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1812
|
+
/**
|
|
1813
|
+
* @method
|
|
1814
|
+
* @name kraken#fetchOrderTrades
|
|
1815
|
+
* @description fetch all the trades made from a single order
|
|
1816
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getTradesInfo
|
|
1817
|
+
* @param {string} id order id
|
|
1818
|
+
* @param {string} symbol unified market symbol
|
|
1819
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
1820
|
+
* @param {int} [limit] the maximum number of trades to retrieve
|
|
1821
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1822
|
+
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
1823
|
+
*/
|
|
1824
|
+
const orderTrades = this.safeValue(params, 'trades');
|
|
1825
|
+
const tradeIds = [];
|
|
1826
|
+
if (orderTrades === undefined) {
|
|
1827
|
+
throw new errors.ArgumentsRequired(this.id + " fetchOrderTrades() requires a unified order structure in the params argument or a 'trades' param (an array of trade id strings)");
|
|
1828
|
+
}
|
|
1829
|
+
else {
|
|
1830
|
+
for (let i = 0; i < orderTrades.length; i++) {
|
|
1831
|
+
const orderTrade = orderTrades[i];
|
|
1832
|
+
if (typeof orderTrade === 'string') {
|
|
1833
|
+
tradeIds.push(orderTrade);
|
|
1834
|
+
}
|
|
1835
|
+
else {
|
|
1836
|
+
tradeIds.push(orderTrade['id']);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
await this.loadMarkets();
|
|
1841
|
+
if (symbol !== undefined) {
|
|
1842
|
+
symbol = this.symbol(symbol);
|
|
1843
|
+
}
|
|
1844
|
+
const options = this.safeValue(this.options, 'fetchOrderTrades', {});
|
|
1845
|
+
const batchSize = this.safeInteger(options, 'batchSize', 20);
|
|
1846
|
+
const numTradeIds = tradeIds.length;
|
|
1847
|
+
let numBatches = this.parseToInt(numTradeIds / batchSize);
|
|
1848
|
+
numBatches = this.sum(numBatches, 1);
|
|
1849
|
+
let result = [];
|
|
1850
|
+
for (let j = 0; j < numBatches; j++) {
|
|
1851
|
+
const requestIds = [];
|
|
1852
|
+
for (let k = 0; k < batchSize; k++) {
|
|
1853
|
+
const index = this.sum(j * batchSize, k);
|
|
1854
|
+
if (index < numTradeIds) {
|
|
1855
|
+
requestIds.push(tradeIds[index]);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
const request = {
|
|
1859
|
+
'txid': requestIds.join(','),
|
|
1860
|
+
};
|
|
1861
|
+
const response = await this.privatePostQueryTrades(request);
|
|
1862
|
+
//
|
|
1863
|
+
// {
|
|
1864
|
+
// "error": [],
|
|
1865
|
+
// "result": {
|
|
1866
|
+
// 'TIMIRG-WUNNE-RRJ6GT': {
|
|
1867
|
+
// "ordertxid": 'OQRPN2-LRHFY-HIFA7D',
|
|
1868
|
+
// "postxid": 'TKH2SE-M7IF5-CFI7LT',
|
|
1869
|
+
// "pair": 'USDCUSDT',
|
|
1870
|
+
// "time": 1586340086.457,
|
|
1871
|
+
// "type": 'sell',
|
|
1872
|
+
// "ordertype": 'market',
|
|
1873
|
+
// "price": '0.99860000',
|
|
1874
|
+
// "cost": '22.16892001',
|
|
1875
|
+
// "fee": '0.04433784',
|
|
1876
|
+
// "vol": '22.20000000',
|
|
1877
|
+
// "margin": '0.00000000',
|
|
1878
|
+
// "misc": ''
|
|
1879
|
+
// }
|
|
1880
|
+
// }
|
|
1881
|
+
// }
|
|
1882
|
+
//
|
|
1883
|
+
const rawTrades = this.safeValue(response, 'result');
|
|
1884
|
+
const ids = Object.keys(rawTrades);
|
|
1885
|
+
for (let i = 0; i < ids.length; i++) {
|
|
1886
|
+
rawTrades[ids[i]]['id'] = ids[i];
|
|
1887
|
+
}
|
|
1888
|
+
const trades = this.parseTrades(rawTrades, undefined, since, limit);
|
|
1889
|
+
const tradesFilteredBySymbol = this.filterBySymbol(trades, symbol);
|
|
1890
|
+
result = this.arrayConcat(result, tradesFilteredBySymbol);
|
|
1891
|
+
}
|
|
1892
|
+
return result;
|
|
1893
|
+
}
|
|
1894
|
+
async fetchOrdersByIds(ids, symbol = undefined, params = {}) {
|
|
1895
|
+
/**
|
|
1896
|
+
* @method
|
|
1897
|
+
* @name kraken#fetchOrdersByIds
|
|
1898
|
+
* @description fetch orders by the list of order id
|
|
1899
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getClosedOrders
|
|
1900
|
+
* @param {string[]|undefined} ids list of order id
|
|
1901
|
+
* @param {object} [params] extra parameters specific to the kraken api endpoint
|
|
1902
|
+
* @returns {object[]} a list of [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1903
|
+
*/
|
|
1904
|
+
await this.loadMarkets();
|
|
1905
|
+
const response = await this.privatePostQueryOrders(this.extend({
|
|
1906
|
+
'trades': true,
|
|
1907
|
+
'txid': ids.join(','), // comma delimited list of transaction ids to query info about (20 maximum)
|
|
1908
|
+
}, params));
|
|
1909
|
+
const result = this.safeValue(response, 'result', {});
|
|
1910
|
+
const orders = [];
|
|
1911
|
+
const orderIds = Object.keys(result);
|
|
1912
|
+
for (let i = 0; i < orderIds.length; i++) {
|
|
1913
|
+
const id = orderIds[i];
|
|
1914
|
+
const item = result[id];
|
|
1915
|
+
const order = this.parseOrder(this.extend({ 'id': id }, item));
|
|
1916
|
+
orders.push(order);
|
|
1917
|
+
}
|
|
1918
|
+
return orders;
|
|
1919
|
+
}
|
|
1920
|
+
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1921
|
+
/**
|
|
1922
|
+
* @method
|
|
1923
|
+
* @name kraken#fetchMyTrades
|
|
1924
|
+
* @description fetch all trades made by the user
|
|
1925
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getTradeHistory
|
|
1926
|
+
* @param {string} symbol unified market symbol
|
|
1927
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
1928
|
+
* @param {int} [limit] the maximum number of trades structures to retrieve
|
|
1929
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1930
|
+
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
1931
|
+
*/
|
|
1932
|
+
await this.loadMarkets();
|
|
1933
|
+
const request = {
|
|
1934
|
+
// 'type': 'all', // any position, closed position, closing position, no position
|
|
1935
|
+
// 'trades': false, // whether or not to include trades related to position in output
|
|
1936
|
+
// 'start': 1234567890, // starting unix timestamp or trade tx id of results (exclusive)
|
|
1937
|
+
// 'end': 1234567890, // ending unix timestamp or trade tx id of results (inclusive)
|
|
1938
|
+
// 'ofs' = result offset
|
|
1939
|
+
};
|
|
1940
|
+
if (since !== undefined) {
|
|
1941
|
+
request['start'] = this.parseToInt(since / 1000);
|
|
1942
|
+
}
|
|
1943
|
+
const response = await this.privatePostTradesHistory(this.extend(request, params));
|
|
1944
|
+
//
|
|
1945
|
+
// {
|
|
1946
|
+
// "error": [],
|
|
1947
|
+
// "result": {
|
|
1948
|
+
// "trades": {
|
|
1949
|
+
// "GJ3NYQ-XJRTF-THZABF": {
|
|
1950
|
+
// "ordertxid": "TKH2SE-ZIF5E-CFI7LT",
|
|
1951
|
+
// "postxid": "OEN3VX-M7IF5-JNBJAM",
|
|
1952
|
+
// "pair": "XICNXETH",
|
|
1953
|
+
// "time": 1527213229.4491,
|
|
1954
|
+
// "type": "sell",
|
|
1955
|
+
// "ordertype": "limit",
|
|
1956
|
+
// "price": "0.001612",
|
|
1957
|
+
// "cost": "0.025792",
|
|
1958
|
+
// "fee": "0.000026",
|
|
1959
|
+
// "vol": "16.00000000",
|
|
1960
|
+
// "margin": "0.000000",
|
|
1961
|
+
// "misc": ""
|
|
1962
|
+
// },
|
|
1963
|
+
// ...
|
|
1964
|
+
// },
|
|
1965
|
+
// "count": 9760,
|
|
1966
|
+
// },
|
|
1967
|
+
// }
|
|
1968
|
+
//
|
|
1969
|
+
const trades = response['result']['trades'];
|
|
1970
|
+
const ids = Object.keys(trades);
|
|
1971
|
+
for (let i = 0; i < ids.length; i++) {
|
|
1972
|
+
trades[ids[i]]['id'] = ids[i];
|
|
1973
|
+
}
|
|
1974
|
+
let market = undefined;
|
|
1975
|
+
if (symbol !== undefined) {
|
|
1976
|
+
market = this.market(symbol);
|
|
1977
|
+
}
|
|
1978
|
+
return this.parseTrades(trades, market, since, limit);
|
|
1979
|
+
}
|
|
1980
|
+
async cancelOrder(id, symbol = undefined, params = {}) {
|
|
1981
|
+
/**
|
|
1982
|
+
* @method
|
|
1983
|
+
* @name kraken#cancelOrder
|
|
1984
|
+
* @description cancels an open order
|
|
1985
|
+
* @see https://docs.kraken.com/rest/#tag/Trading/operation/cancelOrder
|
|
1986
|
+
* @param {string} id order id
|
|
1987
|
+
* @param {string} symbol unified symbol of the market the order was made in
|
|
1988
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1989
|
+
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
1990
|
+
*/
|
|
1991
|
+
await this.loadMarkets();
|
|
1992
|
+
let response = undefined;
|
|
1993
|
+
const clientOrderId = this.safeValue2(params, 'userref', 'clientOrderId', id);
|
|
1994
|
+
const request = {
|
|
1995
|
+
'txid': clientOrderId, // order id or userref
|
|
1996
|
+
};
|
|
1997
|
+
params = this.omit(params, ['userref', 'clientOrderId']);
|
|
1998
|
+
try {
|
|
1999
|
+
response = await this.privatePostCancelOrder(this.extend(request, params));
|
|
2000
|
+
}
|
|
2001
|
+
catch (e) {
|
|
2002
|
+
if (this.last_http_response) {
|
|
2003
|
+
if (this.last_http_response.indexOf('EOrder:Unknown order') >= 0) {
|
|
2004
|
+
throw new errors.OrderNotFound(this.id + ' cancelOrder() error ' + this.last_http_response);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
throw e;
|
|
2008
|
+
}
|
|
2009
|
+
return response;
|
|
2010
|
+
}
|
|
2011
|
+
async cancelOrders(ids, symbol = undefined, params = {}) {
|
|
2012
|
+
/**
|
|
2013
|
+
* @method
|
|
2014
|
+
* @name kraken#cancelOrders
|
|
2015
|
+
* @description cancel multiple orders
|
|
2016
|
+
* @see https://docs.kraken.com/rest/#tag/Trading/operation/cancelOrderBatch
|
|
2017
|
+
* @param {string[]} ids open orders transaction ID (txid) or user reference (userref)
|
|
2018
|
+
* @param {string} symbol unified market symbol
|
|
2019
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2020
|
+
* @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2021
|
+
*/
|
|
2022
|
+
const request = {
|
|
2023
|
+
'orders': ids,
|
|
2024
|
+
};
|
|
2025
|
+
const response = await this.privatePostCancelOrderBatch(this.extend(request, params));
|
|
2026
|
+
//
|
|
2027
|
+
// {
|
|
2028
|
+
// "error": [],
|
|
2029
|
+
// "result": {
|
|
2030
|
+
// "count": 2
|
|
2031
|
+
// }
|
|
2032
|
+
// }
|
|
2033
|
+
//
|
|
2034
|
+
return response;
|
|
2035
|
+
}
|
|
2036
|
+
async cancelAllOrders(symbol = undefined, params = {}) {
|
|
2037
|
+
/**
|
|
2038
|
+
* @method
|
|
2039
|
+
* @name kraken#cancelAllOrders
|
|
2040
|
+
* @description cancel all open orders
|
|
2041
|
+
* @see https://docs.kraken.com/rest/#tag/Trading/operation/cancelAllOrders
|
|
2042
|
+
* @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
|
|
2043
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2044
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2045
|
+
*/
|
|
2046
|
+
await this.loadMarkets();
|
|
2047
|
+
return await this.privatePostCancelAll(params);
|
|
2048
|
+
}
|
|
2049
|
+
async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
2050
|
+
/**
|
|
2051
|
+
* @method
|
|
2052
|
+
* @name kraken#fetchOpenOrders
|
|
2053
|
+
* @description fetch all unfilled currently open orders
|
|
2054
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getOpenOrders
|
|
2055
|
+
* @param {string} symbol unified market symbol
|
|
2056
|
+
* @param {int} [since] the earliest time in ms to fetch open orders for
|
|
2057
|
+
* @param {int} [limit] the maximum number of open orders structures to retrieve
|
|
2058
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2059
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2060
|
+
*/
|
|
2061
|
+
await this.loadMarkets();
|
|
2062
|
+
const request = {};
|
|
2063
|
+
if (since !== undefined) {
|
|
2064
|
+
request['start'] = this.parseToInt(since / 1000);
|
|
2065
|
+
}
|
|
2066
|
+
let query = params;
|
|
2067
|
+
const clientOrderId = this.safeValue2(params, 'userref', 'clientOrderId');
|
|
2068
|
+
if (clientOrderId !== undefined) {
|
|
2069
|
+
request['userref'] = clientOrderId;
|
|
2070
|
+
query = this.omit(params, ['userref', 'clientOrderId']);
|
|
2071
|
+
}
|
|
2072
|
+
const response = await this.privatePostOpenOrders(this.extend(request, query));
|
|
2073
|
+
let market = undefined;
|
|
2074
|
+
if (symbol !== undefined) {
|
|
2075
|
+
market = this.market(symbol);
|
|
2076
|
+
}
|
|
2077
|
+
const result = this.safeValue(response, 'result', {});
|
|
2078
|
+
const orders = this.safeValue(result, 'open', []);
|
|
2079
|
+
return this.parseOrders(orders, market, since, limit);
|
|
2080
|
+
}
|
|
2081
|
+
async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
2082
|
+
/**
|
|
2083
|
+
* @method
|
|
2084
|
+
* @name kraken#fetchClosedOrders
|
|
2085
|
+
* @description fetches information on multiple closed orders made by the user
|
|
2086
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getClosedOrders
|
|
2087
|
+
* @param {string} symbol unified market symbol of the market orders were made in
|
|
2088
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
2089
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
2090
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2091
|
+
* @param {int} [params.until] timestamp in ms of the latest entry
|
|
2092
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2093
|
+
*/
|
|
2094
|
+
await this.loadMarkets();
|
|
2095
|
+
let request = {};
|
|
2096
|
+
if (since !== undefined) {
|
|
2097
|
+
request['start'] = this.parseToInt(since / 1000);
|
|
2098
|
+
}
|
|
2099
|
+
let query = params;
|
|
2100
|
+
const clientOrderId = this.safeValue2(params, 'userref', 'clientOrderId');
|
|
2101
|
+
if (clientOrderId !== undefined) {
|
|
2102
|
+
request['userref'] = clientOrderId;
|
|
2103
|
+
query = this.omit(params, ['userref', 'clientOrderId']);
|
|
2104
|
+
}
|
|
2105
|
+
[request, params] = this.handleUntilOption('end', request, params);
|
|
2106
|
+
const response = await this.privatePostClosedOrders(this.extend(request, query));
|
|
2107
|
+
//
|
|
2108
|
+
// {
|
|
2109
|
+
// "error":[],
|
|
2110
|
+
// "result":{
|
|
2111
|
+
// "closed":{
|
|
2112
|
+
// "OETZYO-UL524-QJMXCT":{
|
|
2113
|
+
// "refid":null,
|
|
2114
|
+
// "userref":null,
|
|
2115
|
+
// "status":"canceled",
|
|
2116
|
+
// "reason":"User requested",
|
|
2117
|
+
// "opentm":1601489313.3898,
|
|
2118
|
+
// "closetm":1601489346.5507,
|
|
2119
|
+
// "starttm":0,
|
|
2120
|
+
// "expiretm":0,
|
|
2121
|
+
// "descr":{
|
|
2122
|
+
// "pair":"ETHUSDT",
|
|
2123
|
+
// "type":"buy",
|
|
2124
|
+
// "ordertype":"limit",
|
|
2125
|
+
// "price":"330.00",
|
|
2126
|
+
// "price2":"0",
|
|
2127
|
+
// "leverage":"none",
|
|
2128
|
+
// "order":"buy 0.02100000 ETHUSDT @ limit 330.00",
|
|
2129
|
+
// "close":""
|
|
2130
|
+
// },
|
|
2131
|
+
// "vol":"0.02100000",
|
|
2132
|
+
// "vol_exec":"0.00000000",
|
|
2133
|
+
// "cost":"0.00000",
|
|
2134
|
+
// "fee":"0.00000",
|
|
2135
|
+
// "price":"0.00000",
|
|
2136
|
+
// "stopprice":"0.00000",
|
|
2137
|
+
// "limitprice":"0.00000",
|
|
2138
|
+
// "misc":"",
|
|
2139
|
+
// "oflags":"fciq"
|
|
2140
|
+
// },
|
|
2141
|
+
// },
|
|
2142
|
+
// "count":16
|
|
2143
|
+
// }
|
|
2144
|
+
// }
|
|
2145
|
+
//
|
|
2146
|
+
let market = undefined;
|
|
2147
|
+
if (symbol !== undefined) {
|
|
2148
|
+
market = this.market(symbol);
|
|
2149
|
+
}
|
|
2150
|
+
const result = this.safeValue(response, 'result', {});
|
|
2151
|
+
const orders = this.safeValue(result, 'closed', []);
|
|
2152
|
+
return this.parseOrders(orders, market, since, limit);
|
|
2153
|
+
}
|
|
2154
|
+
parseTransactionStatus(status) {
|
|
2155
|
+
// IFEX transaction states
|
|
2156
|
+
const statuses = {
|
|
2157
|
+
'Initial': 'pending',
|
|
2158
|
+
'Pending': 'pending',
|
|
2159
|
+
'Success': 'ok',
|
|
2160
|
+
'Settled': 'pending',
|
|
2161
|
+
'Failure': 'failed',
|
|
2162
|
+
'Partial': 'ok',
|
|
2163
|
+
};
|
|
2164
|
+
return this.safeString(statuses, status, status);
|
|
2165
|
+
}
|
|
2166
|
+
parseNetwork(network) {
|
|
2167
|
+
const withdrawMethods = this.safeValue(this.options, 'withdrawMethods', {});
|
|
2168
|
+
return this.safeString(withdrawMethods, network, network);
|
|
2169
|
+
}
|
|
2170
|
+
parseTransaction(transaction, currency = undefined) {
|
|
2171
|
+
//
|
|
2172
|
+
// fetchDeposits
|
|
2173
|
+
//
|
|
2174
|
+
// {
|
|
2175
|
+
// "method": "Ether (Hex)",
|
|
2176
|
+
// "aclass": "currency",
|
|
2177
|
+
// "asset": "XETH",
|
|
2178
|
+
// "refid": "Q2CANKL-LBFVEE-U4Y2WQ",
|
|
2179
|
+
// "txid": "0x57fd704dab1a73c20e24c8696099b695d596924b401b261513cfdab23…",
|
|
2180
|
+
// "info": "0x615f9ba7a9575b0ab4d571b2b36b1b324bd83290",
|
|
2181
|
+
// "amount": "7.9999257900",
|
|
2182
|
+
// "fee": "0.0000000000",
|
|
2183
|
+
// "time": 1529223212,
|
|
2184
|
+
// "status": "Success"
|
|
2185
|
+
// }
|
|
2186
|
+
//
|
|
2187
|
+
// there can be an additional 'status-prop' field present
|
|
2188
|
+
// deposit pending review by exchange => 'on-hold'
|
|
2189
|
+
// the deposit is initiated by the exchange => 'return'
|
|
2190
|
+
//
|
|
2191
|
+
// {
|
|
2192
|
+
// "type": 'deposit',
|
|
2193
|
+
// "method": 'Fidor Bank AG (Wire Transfer)',
|
|
2194
|
+
// "aclass": 'currency',
|
|
2195
|
+
// "asset": 'ZEUR',
|
|
2196
|
+
// "refid": 'xxx-xxx-xxx',
|
|
2197
|
+
// "txid": '12341234',
|
|
2198
|
+
// "info": 'BANKCODEXXX',
|
|
2199
|
+
// "amount": '38769.08',
|
|
2200
|
+
// "fee": '0.0000',
|
|
2201
|
+
// "time": 1644306552,
|
|
2202
|
+
// "status": 'Success',
|
|
2203
|
+
// status-prop: 'on-hold'
|
|
2204
|
+
// }
|
|
2205
|
+
//
|
|
2206
|
+
//
|
|
2207
|
+
// fetchWithdrawals
|
|
2208
|
+
//
|
|
2209
|
+
// {
|
|
2210
|
+
// "method": "Ether",
|
|
2211
|
+
// "aclass": "currency",
|
|
2212
|
+
// "asset": "XETH",
|
|
2213
|
+
// "refid": "A2BF34S-O7LBNQ-UE4Y4O",
|
|
2214
|
+
// "txid": "0x288b83c6b0904d8400ef44e1c9e2187b5c8f7ea3d838222d53f701a15b5c274d",
|
|
2215
|
+
// "info": "0x7cb275a5e07ba943fee972e165d80daa67cb2dd0",
|
|
2216
|
+
// "amount": "9.9950000000",
|
|
2217
|
+
// "fee": "0.0050000000",
|
|
2218
|
+
// "time": 1530481750,
|
|
2219
|
+
// "status": "Success"
|
|
2220
|
+
// "key":"Huobi wallet",
|
|
2221
|
+
// "network":"Tron"
|
|
2222
|
+
// status-prop: 'on-hold' // this field might not be present in some cases
|
|
2223
|
+
// }
|
|
2224
|
+
//
|
|
2225
|
+
// withdraw
|
|
2226
|
+
//
|
|
2227
|
+
// {
|
|
2228
|
+
// "refid": "AGBSO6T-UFMTTQ-I7KGS6"
|
|
2229
|
+
// }
|
|
2230
|
+
//
|
|
2231
|
+
const id = this.safeString(transaction, 'refid');
|
|
2232
|
+
const txid = this.safeString(transaction, 'txid');
|
|
2233
|
+
const timestamp = this.safeTimestamp(transaction, 'time');
|
|
2234
|
+
const currencyId = this.safeString(transaction, 'asset');
|
|
2235
|
+
const code = this.safeCurrencyCode(currencyId, currency);
|
|
2236
|
+
const address = this.safeString(transaction, 'info');
|
|
2237
|
+
const amount = this.safeNumber(transaction, 'amount');
|
|
2238
|
+
let status = this.parseTransactionStatus(this.safeString(transaction, 'status'));
|
|
2239
|
+
const statusProp = this.safeString(transaction, 'status-prop');
|
|
2240
|
+
const isOnHoldDeposit = statusProp === 'on-hold';
|
|
2241
|
+
const isCancellationRequest = statusProp === 'cancel-pending';
|
|
2242
|
+
const isOnHoldWithdrawal = statusProp === 'onhold';
|
|
2243
|
+
if (isOnHoldDeposit || isCancellationRequest || isOnHoldWithdrawal) {
|
|
2244
|
+
status = 'pending';
|
|
2245
|
+
}
|
|
2246
|
+
const type = this.safeString(transaction, 'type'); // injected from the outside
|
|
2247
|
+
let feeCost = this.safeNumber(transaction, 'fee');
|
|
2248
|
+
if (feeCost === undefined) {
|
|
2249
|
+
if (type === 'deposit') {
|
|
2250
|
+
feeCost = 0;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
return {
|
|
2254
|
+
'info': transaction,
|
|
2255
|
+
'id': id,
|
|
2256
|
+
'currency': code,
|
|
2257
|
+
'amount': amount,
|
|
2258
|
+
'network': this.parseNetwork(this.safeString(transaction, 'network')),
|
|
2259
|
+
'address': address,
|
|
2260
|
+
'addressTo': undefined,
|
|
2261
|
+
'addressFrom': undefined,
|
|
2262
|
+
'tag': undefined,
|
|
2263
|
+
'tagTo': undefined,
|
|
2264
|
+
'tagFrom': undefined,
|
|
2265
|
+
'status': status,
|
|
2266
|
+
'type': type,
|
|
2267
|
+
'updated': undefined,
|
|
2268
|
+
'txid': txid,
|
|
2269
|
+
'timestamp': timestamp,
|
|
2270
|
+
'datetime': this.iso8601(timestamp),
|
|
2271
|
+
'comment': undefined,
|
|
2272
|
+
'internal': undefined,
|
|
2273
|
+
'fee': {
|
|
2274
|
+
'currency': code,
|
|
2275
|
+
'cost': feeCost,
|
|
2276
|
+
},
|
|
2277
|
+
};
|
|
2278
|
+
}
|
|
2279
|
+
parseTransactionsByType(type, transactions, code = undefined, since = undefined, limit = undefined) {
|
|
2280
|
+
const result = [];
|
|
2281
|
+
for (let i = 0; i < transactions.length; i++) {
|
|
2282
|
+
const transaction = this.parseTransaction(this.extend({
|
|
2283
|
+
'type': type,
|
|
2284
|
+
}, transactions[i]));
|
|
2285
|
+
result.push(transaction);
|
|
2286
|
+
}
|
|
2287
|
+
return this.filterByCurrencySinceLimit(result, code, since, limit);
|
|
2288
|
+
}
|
|
2289
|
+
async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
2290
|
+
/**
|
|
2291
|
+
* @method
|
|
2292
|
+
* @name kraken#fetchDeposits
|
|
2293
|
+
* @description fetch all deposits made to an account
|
|
2294
|
+
* @see https://docs.kraken.com/rest/#tag/Funding/operation/getStatusRecentDeposits
|
|
2295
|
+
* @param {string} code unified currency code
|
|
2296
|
+
* @param {int} [since] the earliest time in ms to fetch deposits for
|
|
2297
|
+
* @param {int} [limit] the maximum number of deposits structures to retrieve
|
|
2298
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2299
|
+
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
2300
|
+
*/
|
|
2301
|
+
// https://www.kraken.com/en-us/help/api#deposit-status
|
|
2302
|
+
if (code === undefined) {
|
|
2303
|
+
throw new errors.ArgumentsRequired(this.id + ' fetchDeposits() requires a currency code argument');
|
|
2304
|
+
}
|
|
2305
|
+
await this.loadMarkets();
|
|
2306
|
+
const currency = this.currency(code);
|
|
2307
|
+
const request = {
|
|
2308
|
+
'asset': currency['id'],
|
|
2309
|
+
};
|
|
2310
|
+
if (since !== undefined) {
|
|
2311
|
+
request['start'] = since;
|
|
2312
|
+
}
|
|
2313
|
+
const response = await this.privatePostDepositStatus(this.extend(request, params));
|
|
2314
|
+
//
|
|
2315
|
+
// { error: [],
|
|
2316
|
+
// "result": [ { "method": "Ether (Hex)",
|
|
2317
|
+
// "aclass": "currency",
|
|
2318
|
+
// "asset": "XETH",
|
|
2319
|
+
// "refid": "Q2CANKL-LBFVEE-U4Y2WQ",
|
|
2320
|
+
// "txid": "0x57fd704dab1a73c20e24c8696099b695d596924b401b261513cfdab23…",
|
|
2321
|
+
// "info": "0x615f9ba7a9575b0ab4d571b2b36b1b324bd83290",
|
|
2322
|
+
// "amount": "7.9999257900",
|
|
2323
|
+
// "fee": "0.0000000000",
|
|
2324
|
+
// "time": 1529223212,
|
|
2325
|
+
// "status": "Success" } ] }
|
|
2326
|
+
//
|
|
2327
|
+
return this.parseTransactionsByType('deposit', response['result'], code, since, limit);
|
|
2328
|
+
}
|
|
2329
|
+
async fetchTime(params = {}) {
|
|
2330
|
+
/**
|
|
2331
|
+
* @method
|
|
2332
|
+
* @name kraken#fetchTime
|
|
2333
|
+
* @description fetches the current integer timestamp in milliseconds from the exchange server
|
|
2334
|
+
* @see https://docs.kraken.com/rest/#tag/Market-Data/operation/getServerTime
|
|
2335
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2336
|
+
* @returns {int} the current integer timestamp in milliseconds from the exchange server
|
|
2337
|
+
*/
|
|
2338
|
+
// https://www.kraken.com/en-us/features/api#get-server-time
|
|
2339
|
+
const response = await this.publicGetTime(params);
|
|
2340
|
+
//
|
|
2341
|
+
// {
|
|
2342
|
+
// "error": [],
|
|
2343
|
+
// "result": {
|
|
2344
|
+
// "unixtime": 1591502873,
|
|
2345
|
+
// "rfc1123": "Sun, 7 Jun 20 04:07:53 +0000"
|
|
2346
|
+
// }
|
|
2347
|
+
// }
|
|
2348
|
+
//
|
|
2349
|
+
const result = this.safeValue(response, 'result', {});
|
|
2350
|
+
return this.safeTimestamp(result, 'unixtime');
|
|
2351
|
+
}
|
|
2352
|
+
async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
2353
|
+
/**
|
|
2354
|
+
* @method
|
|
2355
|
+
* @name kraken#fetchWithdrawals
|
|
2356
|
+
* @description fetch all withdrawals made from an account
|
|
2357
|
+
* @see https://docs.kraken.com/rest/#tag/Funding/operation/getStatusRecentWithdrawals
|
|
2358
|
+
* @param {string} code unified currency code
|
|
2359
|
+
* @param {int} [since] the earliest time in ms to fetch withdrawals for
|
|
2360
|
+
* @param {int} [limit] the maximum number of withdrawals structures to retrieve
|
|
2361
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2362
|
+
* @param {object} [params.end] End timestamp, withdrawals created strictly after will be not be included in the response
|
|
2363
|
+
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times
|
|
2364
|
+
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
2365
|
+
*/
|
|
2366
|
+
await this.loadMarkets();
|
|
2367
|
+
let paginate = false;
|
|
2368
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchWithdrawals', 'paginate');
|
|
2369
|
+
if (paginate) {
|
|
2370
|
+
params['cursor'] = true;
|
|
2371
|
+
return await this.fetchPaginatedCallCursor('fetchWithdrawals', code, since, limit, params, 'next_cursor', 'cursor');
|
|
2372
|
+
}
|
|
2373
|
+
const request = {};
|
|
2374
|
+
if (code !== undefined) {
|
|
2375
|
+
const currency = this.currency(code);
|
|
2376
|
+
request['asset'] = currency['id'];
|
|
2377
|
+
}
|
|
2378
|
+
if (since !== undefined) {
|
|
2379
|
+
request['since'] = since.toString();
|
|
2380
|
+
}
|
|
2381
|
+
const response = await this.privatePostWithdrawStatus(this.extend(request, params));
|
|
2382
|
+
//
|
|
2383
|
+
// with no pagination
|
|
2384
|
+
// { error: [],
|
|
2385
|
+
// "result": [ { "method": "Ether",
|
|
2386
|
+
// "aclass": "currency",
|
|
2387
|
+
// "asset": "XETH",
|
|
2388
|
+
// "refid": "A2BF34S-O7LBNQ-UE4Y4O",
|
|
2389
|
+
// "txid": "0x298c83c7b0904d8400ef43e1c9e2287b518f7ea3d838822d53f704a1565c274d",
|
|
2390
|
+
// "info": "0x7cb275a5e07ba943fee972e165d80daa67cb2dd0",
|
|
2391
|
+
// "amount": "9.9950000000",
|
|
2392
|
+
// "fee": "0.0050000000",
|
|
2393
|
+
// "time": 1530481750,
|
|
2394
|
+
// "status": "Success" } ] }
|
|
2395
|
+
// with pagination
|
|
2396
|
+
// {
|
|
2397
|
+
// "error":[],
|
|
2398
|
+
// "result":{
|
|
2399
|
+
// "withdrawals":[
|
|
2400
|
+
// {
|
|
2401
|
+
// "method":"Tether USD (TRC20)",
|
|
2402
|
+
// "aclass":"currency",
|
|
2403
|
+
// "asset":"USDT",
|
|
2404
|
+
// "refid":"BSNFZU2-MEFN4G-J3NEZV",
|
|
2405
|
+
// "txid":"1c7a642fb7387bbc2c6a2c509fd1ae146937f4cf793b4079a4f0715e3a02615a",
|
|
2406
|
+
// "info":"TQmdxSuC16EhFg8FZWtYgrfFRosoRF7bCp",
|
|
2407
|
+
// "amount":"1996.50000000",
|
|
2408
|
+
// "fee":"2.50000000",
|
|
2409
|
+
// "time":1669126657,
|
|
2410
|
+
// "status":"Success",
|
|
2411
|
+
// "key":"poloniex",
|
|
2412
|
+
// "network":"Tron"
|
|
2413
|
+
// },
|
|
2414
|
+
// ...
|
|
2415
|
+
// ],
|
|
2416
|
+
// "next_cursor":"HgAAAAAAAABGVFRSd3k1LVF4Y0JQY05Gd0xRY0NxenFndHpybkwBAQH2AwEBAAAAAQAAAAAAAAABAAAAAAAZAAAAAAAAAA=="
|
|
2417
|
+
// }
|
|
2418
|
+
// }
|
|
2419
|
+
//
|
|
2420
|
+
let rawWithdrawals = undefined;
|
|
2421
|
+
const result = this.safeValue(response, 'result');
|
|
2422
|
+
if (!Array.isArray(result)) {
|
|
2423
|
+
rawWithdrawals = this.addPaginationCursorToResult(result);
|
|
2424
|
+
}
|
|
2425
|
+
else {
|
|
2426
|
+
rawWithdrawals = result;
|
|
2427
|
+
}
|
|
2428
|
+
return this.parseTransactionsByType('withdrawal', rawWithdrawals, code, since, limit);
|
|
2429
|
+
}
|
|
2430
|
+
addPaginationCursorToResult(result) {
|
|
2431
|
+
const cursor = this.safeString(result, 'next_cursor');
|
|
2432
|
+
const data = this.safeValue(result, 'withdrawals');
|
|
2433
|
+
const dataLength = data.length;
|
|
2434
|
+
if (cursor !== undefined && dataLength > 0) {
|
|
2435
|
+
const last = data[dataLength - 1];
|
|
2436
|
+
last['next_cursor'] = cursor;
|
|
2437
|
+
data[dataLength - 1] = last;
|
|
2438
|
+
}
|
|
2439
|
+
return data;
|
|
2440
|
+
}
|
|
2441
|
+
async createDepositAddress(code, params = {}) {
|
|
2442
|
+
/**
|
|
2443
|
+
* @method
|
|
2444
|
+
* @name kraken#createDepositAddress
|
|
2445
|
+
* @description create a currency deposit address
|
|
2446
|
+
* @see https://docs.kraken.com/rest/#tag/Funding/operation/getDepositAddresses
|
|
2447
|
+
* @param {string} code unified currency code of the currency for the deposit address
|
|
2448
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2449
|
+
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
|
|
2450
|
+
*/
|
|
2451
|
+
const request = {
|
|
2452
|
+
'new': 'true',
|
|
2453
|
+
};
|
|
2454
|
+
return await this.fetchDepositAddress(code, this.extend(request, params));
|
|
2455
|
+
}
|
|
2456
|
+
async fetchDepositMethods(code, params = {}) {
|
|
2457
|
+
/**
|
|
2458
|
+
* @method
|
|
2459
|
+
* @name kraken#fetchDepositMethods
|
|
2460
|
+
* @description fetch deposit methods for a currency associated with this account
|
|
2461
|
+
* @see https://docs.kraken.com/rest/#tag/Funding/operation/getDepositMethods
|
|
2462
|
+
* @param {string} code unified currency code
|
|
2463
|
+
* @param {object} [params] extra parameters specific to the kraken api endpoint
|
|
2464
|
+
* @returns {object} of deposit methods
|
|
2465
|
+
*/
|
|
2466
|
+
await this.loadMarkets();
|
|
2467
|
+
const currency = this.currency(code);
|
|
2468
|
+
const request = {
|
|
2469
|
+
'asset': currency['id'],
|
|
2470
|
+
};
|
|
2471
|
+
const response = await this.privatePostDepositMethods(this.extend(request, params));
|
|
2472
|
+
//
|
|
2473
|
+
// {
|
|
2474
|
+
// "error":[],
|
|
2475
|
+
// "result":[
|
|
2476
|
+
// {"method":"Ether (Hex)","limit":false,"gen-address":true}
|
|
2477
|
+
// ]
|
|
2478
|
+
// }
|
|
2479
|
+
//
|
|
2480
|
+
// {
|
|
2481
|
+
// "error":[],
|
|
2482
|
+
// "result":[
|
|
2483
|
+
// {"method":"Tether USD (ERC20)","limit":false,"address-setup-fee":"0.00000000","gen-address":true},
|
|
2484
|
+
// {"method":"Tether USD (TRC20)","limit":false,"address-setup-fee":"0.00000000","gen-address":true}
|
|
2485
|
+
// ]
|
|
2486
|
+
// }
|
|
2487
|
+
//
|
|
2488
|
+
// {
|
|
2489
|
+
// "error":[],
|
|
2490
|
+
// "result":[
|
|
2491
|
+
// {"method":"Bitcoin","limit":false,"fee":"0.0000000000","gen-address":true}
|
|
2492
|
+
// ]
|
|
2493
|
+
// }
|
|
2494
|
+
//
|
|
2495
|
+
return this.safeValue(response, 'result');
|
|
2496
|
+
}
|
|
2497
|
+
async fetchDepositAddress(code, params = {}) {
|
|
2498
|
+
/**
|
|
2499
|
+
* @method
|
|
2500
|
+
* @name kraken#fetchDepositAddress
|
|
2501
|
+
* @description fetch the deposit address for a currency associated with this account
|
|
2502
|
+
* @see https://docs.kraken.com/rest/#tag/Funding/operation/getDepositAddresses
|
|
2503
|
+
* @param {string} code unified currency code
|
|
2504
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2505
|
+
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
|
|
2506
|
+
*/
|
|
2507
|
+
await this.loadMarkets();
|
|
2508
|
+
const currency = this.currency(code);
|
|
2509
|
+
let network = this.safeStringUpper(params, 'network');
|
|
2510
|
+
const networks = this.safeValue(this.options, 'networks', {});
|
|
2511
|
+
network = this.safeString(networks, network, network); // support ETH > ERC20 aliases
|
|
2512
|
+
params = this.omit(params, 'network');
|
|
2513
|
+
if ((code === 'USDT') && (network === 'TRC20')) {
|
|
2514
|
+
code = code + '-' + network;
|
|
2515
|
+
}
|
|
2516
|
+
const defaultDepositMethods = this.safeValue(this.options, 'depositMethods', {});
|
|
2517
|
+
const defaultDepositMethod = this.safeString(defaultDepositMethods, code);
|
|
2518
|
+
let depositMethod = this.safeString(params, 'method', defaultDepositMethod);
|
|
2519
|
+
// if the user has specified an exchange-specific method in params
|
|
2520
|
+
// we pass it as is, otherwise we take the 'network' unified param
|
|
2521
|
+
if (depositMethod === undefined) {
|
|
2522
|
+
const depositMethods = await this.fetchDepositMethods(code);
|
|
2523
|
+
if (network !== undefined) {
|
|
2524
|
+
// find best matching deposit method, or fallback to the first one
|
|
2525
|
+
for (let i = 0; i < depositMethods.length; i++) {
|
|
2526
|
+
const entry = this.safeString(depositMethods[i], 'method');
|
|
2527
|
+
if (entry.indexOf(network) >= 0) {
|
|
2528
|
+
depositMethod = entry;
|
|
2529
|
+
break;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
// if depositMethod was not specified, fallback to the first available deposit method
|
|
2534
|
+
if (depositMethod === undefined) {
|
|
2535
|
+
const firstDepositMethod = this.safeValue(depositMethods, 0, {});
|
|
2536
|
+
depositMethod = this.safeString(firstDepositMethod, 'method');
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
const request = {
|
|
2540
|
+
'asset': currency['id'],
|
|
2541
|
+
'method': depositMethod,
|
|
2542
|
+
};
|
|
2543
|
+
const response = await this.privatePostDepositAddresses(this.extend(request, params));
|
|
2544
|
+
//
|
|
2545
|
+
// {
|
|
2546
|
+
// "error":[],
|
|
2547
|
+
// "result":[
|
|
2548
|
+
// {"address":"0x77b5051f97efa9cc52c9ad5b023a53fc15c200d3","expiretm":"0"}
|
|
2549
|
+
// ]
|
|
2550
|
+
// }
|
|
2551
|
+
//
|
|
2552
|
+
const result = this.safeValue(response, 'result', []);
|
|
2553
|
+
const firstResult = this.safeValue(result, 0, {});
|
|
2554
|
+
if (firstResult === undefined) {
|
|
2555
|
+
throw new errors.InvalidAddress(this.id + ' privatePostDepositAddresses() returned no addresses for ' + code);
|
|
2556
|
+
}
|
|
2557
|
+
return this.parseDepositAddress(firstResult, currency);
|
|
2558
|
+
}
|
|
2559
|
+
parseDepositAddress(depositAddress, currency = undefined) {
|
|
2560
|
+
//
|
|
2561
|
+
// {
|
|
2562
|
+
// "address":"0x77b5051f97efa9cc52c9ad5b023a53fc15c200d3",
|
|
2563
|
+
// "expiretm":"0"
|
|
2564
|
+
// }
|
|
2565
|
+
//
|
|
2566
|
+
const address = this.safeString(depositAddress, 'address');
|
|
2567
|
+
const tag = this.safeString(depositAddress, 'tag');
|
|
2568
|
+
currency = this.safeCurrency(undefined, currency);
|
|
2569
|
+
const code = currency['code'];
|
|
2570
|
+
this.checkAddress(address);
|
|
2571
|
+
return {
|
|
2572
|
+
'currency': code,
|
|
2573
|
+
'address': address,
|
|
2574
|
+
'tag': tag,
|
|
2575
|
+
'network': undefined,
|
|
2576
|
+
'info': depositAddress,
|
|
2577
|
+
};
|
|
2578
|
+
}
|
|
2579
|
+
async withdraw(code, amount, address, tag = undefined, params = {}) {
|
|
2580
|
+
/**
|
|
2581
|
+
* @method
|
|
2582
|
+
* @name kraken#withdraw
|
|
2583
|
+
* @description make a withdrawal
|
|
2584
|
+
* @see https://docs.kraken.com/rest/#tag/Funding/operation/withdrawFunds
|
|
2585
|
+
* @param {string} code unified currency code
|
|
2586
|
+
* @param {float} amount the amount to withdraw
|
|
2587
|
+
* @param {string} address the address to withdraw to
|
|
2588
|
+
* @param {string} tag
|
|
2589
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2590
|
+
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
2591
|
+
*/
|
|
2592
|
+
[tag, params] = this.handleWithdrawTagAndParams(tag, params);
|
|
2593
|
+
this.checkAddress(address);
|
|
2594
|
+
if ('key' in params) {
|
|
2595
|
+
await this.loadMarkets();
|
|
2596
|
+
const currency = this.currency(code);
|
|
2597
|
+
const request = {
|
|
2598
|
+
'asset': currency['id'],
|
|
2599
|
+
'amount': amount,
|
|
2600
|
+
'address': address,
|
|
2601
|
+
};
|
|
2602
|
+
const response = await this.privatePostWithdraw(this.extend(request, params));
|
|
2603
|
+
//
|
|
2604
|
+
// {
|
|
2605
|
+
// "error": [],
|
|
2606
|
+
// "result": {
|
|
2607
|
+
// "refid": "AGBSO6T-UFMTTQ-I7KGS6"
|
|
2608
|
+
// }
|
|
2609
|
+
// }
|
|
2610
|
+
//
|
|
2611
|
+
const result = this.safeValue(response, 'result', {});
|
|
2612
|
+
return this.parseTransaction(result, currency);
|
|
2613
|
+
}
|
|
2614
|
+
throw new errors.ExchangeError(this.id + " withdraw() requires a 'key' parameter (withdrawal key name, as set up on your account)");
|
|
2615
|
+
}
|
|
2616
|
+
async fetchPositions(symbols = undefined, params = {}) {
|
|
2617
|
+
/**
|
|
2618
|
+
* @method
|
|
2619
|
+
* @name kraken#fetchPositions
|
|
2620
|
+
* @description fetch all open positions
|
|
2621
|
+
* @see https://docs.kraken.com/rest/#tag/Account-Data/operation/getOpenPositions
|
|
2622
|
+
* @param {string[]|undefined} symbols not used by kraken fetchPositions ()
|
|
2623
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2624
|
+
* @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
2625
|
+
*/
|
|
2626
|
+
await this.loadMarkets();
|
|
2627
|
+
const request = {
|
|
2628
|
+
// 'txid': 'comma delimited list of transaction ids to restrict output to',
|
|
2629
|
+
// 'docalcs': false, // whether or not to include profit/loss calculations
|
|
2630
|
+
// 'consolidation': 'market', // what to consolidate the positions data around, market will consolidate positions based on market pair
|
|
2631
|
+
};
|
|
2632
|
+
const response = await this.privatePostOpenPositions(this.extend(request, params));
|
|
2633
|
+
//
|
|
2634
|
+
// no consolidation
|
|
2635
|
+
//
|
|
2636
|
+
// {
|
|
2637
|
+
// "error": [],
|
|
2638
|
+
// "result": {
|
|
2639
|
+
// 'TGUFMY-FLESJ-VYIX3J': {
|
|
2640
|
+
// "ordertxid": "O3LRNU-ZKDG5-XNCDFR",
|
|
2641
|
+
// "posstatus": "open",
|
|
2642
|
+
// "pair": "ETHUSDT",
|
|
2643
|
+
// "time": 1611557231.4584,
|
|
2644
|
+
// "type": "buy",
|
|
2645
|
+
// "ordertype": "market",
|
|
2646
|
+
// "cost": "28.49800",
|
|
2647
|
+
// "fee": "0.07979",
|
|
2648
|
+
// "vol": "0.02000000",
|
|
2649
|
+
// "vol_closed": "0.00000000",
|
|
2650
|
+
// "margin": "14.24900",
|
|
2651
|
+
// "terms": "0.0200% per 4 hours",
|
|
2652
|
+
// "rollovertm": "1611571631",
|
|
2653
|
+
// "misc": "",
|
|
2654
|
+
// "oflags": ""
|
|
2655
|
+
// }
|
|
2656
|
+
// }
|
|
2657
|
+
// }
|
|
2658
|
+
//
|
|
2659
|
+
// consolidation by market
|
|
2660
|
+
//
|
|
2661
|
+
// {
|
|
2662
|
+
// "error": [],
|
|
2663
|
+
// "result": [
|
|
2664
|
+
// {
|
|
2665
|
+
// "pair": "ETHUSDT",
|
|
2666
|
+
// "positions": "1",
|
|
2667
|
+
// "type": "buy",
|
|
2668
|
+
// "leverage": "2.00000",
|
|
2669
|
+
// "cost": "28.49800",
|
|
2670
|
+
// "fee": "0.07979",
|
|
2671
|
+
// "vol": "0.02000000",
|
|
2672
|
+
// "vol_closed": "0.00000000",
|
|
2673
|
+
// "margin": "14.24900"
|
|
2674
|
+
// }
|
|
2675
|
+
// ]
|
|
2676
|
+
// }
|
|
2677
|
+
//
|
|
2678
|
+
const result = this.safeValue(response, 'result');
|
|
2679
|
+
// todo unify parsePosition/parsePositions
|
|
2680
|
+
return result;
|
|
2681
|
+
}
|
|
2682
|
+
parseAccount(account) {
|
|
2683
|
+
const accountByType = {
|
|
2684
|
+
'spot': 'Spot Wallet',
|
|
2685
|
+
'swap': 'Futures Wallet',
|
|
2686
|
+
'future': 'Futures Wallet',
|
|
2687
|
+
};
|
|
2688
|
+
return this.safeString(accountByType, account, account);
|
|
2689
|
+
}
|
|
2690
|
+
async transferOut(code, amount, params = {}) {
|
|
2691
|
+
/**
|
|
2692
|
+
* @description transfer from spot wallet to futures wallet
|
|
2693
|
+
* @see https://docs.kraken.com/rest/#tag/User-Funding/operation/walletTransfer
|
|
2694
|
+
* @param {str} code Unified currency code
|
|
2695
|
+
* @param {float} amount Size of the transfer
|
|
2696
|
+
* @param {dict} [params] Exchange specific parameters
|
|
2697
|
+
* @returns a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
|
|
2698
|
+
*/
|
|
2699
|
+
return await this.transfer(code, amount, 'spot', 'swap', params);
|
|
2700
|
+
}
|
|
2701
|
+
async transfer(code, amount, fromAccount, toAccount, params = {}) {
|
|
2702
|
+
/**
|
|
2703
|
+
* @method
|
|
2704
|
+
* @name kraken#transfer
|
|
2705
|
+
* @see https://docs.kraken.com/rest/#tag/User-Funding/operation/walletTransfer
|
|
2706
|
+
* @description transfers currencies between sub-accounts (only spot->swap direction is supported)
|
|
2707
|
+
* @param {string} code Unified currency code
|
|
2708
|
+
* @param {float} amount Size of the transfer
|
|
2709
|
+
* @param {string} fromAccount 'spot' or 'Spot Wallet'
|
|
2710
|
+
* @param {string} toAccount 'swap' or 'Futures Wallet'
|
|
2711
|
+
* @param {object} [params] Exchange specific parameters
|
|
2712
|
+
* @returns a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
|
|
2713
|
+
*/
|
|
2714
|
+
await this.loadMarkets();
|
|
2715
|
+
const currency = this.currency(code);
|
|
2716
|
+
fromAccount = this.parseAccount(fromAccount);
|
|
2717
|
+
toAccount = this.parseAccount(toAccount);
|
|
2718
|
+
const request = {
|
|
2719
|
+
'amount': this.currencyToPrecision(code, amount),
|
|
2720
|
+
'from': fromAccount,
|
|
2721
|
+
'to': toAccount,
|
|
2722
|
+
'asset': currency['id'],
|
|
2723
|
+
};
|
|
2724
|
+
if (fromAccount !== 'Spot Wallet') {
|
|
2725
|
+
throw new errors.BadRequest(this.id + ' transfer cannot transfer from ' + fromAccount + ' to ' + toAccount + '. Use krakenfutures instead to transfer from the futures account.');
|
|
2726
|
+
}
|
|
2727
|
+
const response = await this.privatePostWalletTransfer(this.extend(request, params));
|
|
2728
|
+
//
|
|
2729
|
+
// {
|
|
2730
|
+
// "error":[
|
|
2731
|
+
// ],
|
|
2732
|
+
// "result":{
|
|
2733
|
+
// "refid":"BOIUSIF-M7DLMN-UXZ3P5"
|
|
2734
|
+
// }
|
|
2735
|
+
// }
|
|
2736
|
+
//
|
|
2737
|
+
const transfer = this.parseTransfer(response, currency);
|
|
2738
|
+
return this.extend(transfer, {
|
|
2739
|
+
'amount': amount,
|
|
2740
|
+
'fromAccount': fromAccount,
|
|
2741
|
+
'toAccount': toAccount,
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
2744
|
+
parseTransfer(transfer, currency = undefined) {
|
|
2745
|
+
//
|
|
2746
|
+
// transfer
|
|
2747
|
+
//
|
|
2748
|
+
// {
|
|
2749
|
+
// "error":[
|
|
2750
|
+
// ],
|
|
2751
|
+
// "result":{
|
|
2752
|
+
// "refid":"BOIUSIF-M7DLMN-UXZ3P5"
|
|
2753
|
+
// }
|
|
2754
|
+
// }
|
|
2755
|
+
//
|
|
2756
|
+
const result = this.safeValue(transfer, 'result', {});
|
|
2757
|
+
const refid = this.safeString(result, 'refid');
|
|
2758
|
+
return {
|
|
2759
|
+
'info': transfer,
|
|
2760
|
+
'id': refid,
|
|
2761
|
+
'timestamp': undefined,
|
|
2762
|
+
'datetime': undefined,
|
|
2763
|
+
'currency': this.safeString(currency, 'code'),
|
|
2764
|
+
'amount': undefined,
|
|
2765
|
+
'fromAccount': undefined,
|
|
2766
|
+
'toAccount': undefined,
|
|
2767
|
+
'status': 'sucess',
|
|
2768
|
+
};
|
|
2769
|
+
}
|
|
2770
|
+
sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
|
2771
|
+
let url = '/' + this.version + '/' + api + '/' + path;
|
|
2772
|
+
if (api === 'public') {
|
|
2773
|
+
if (Object.keys(params).length) {
|
|
2774
|
+
// urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872
|
|
2775
|
+
url += '?' + this.urlencodeNested(params);
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
else if (api === 'private') {
|
|
2779
|
+
const isCancelOrderBatch = (path === 'CancelOrderBatch');
|
|
2780
|
+
this.checkRequiredCredentials();
|
|
2781
|
+
const nonce = this.nonce().toString();
|
|
2782
|
+
// urlencodeNested is used to address https://github.com/ccxt/ccxt/issues/12872
|
|
2783
|
+
if (isCancelOrderBatch) {
|
|
2784
|
+
body = this.json(this.extend({ 'nonce': nonce }, params));
|
|
2785
|
+
}
|
|
2786
|
+
else {
|
|
2787
|
+
body = this.urlencodeNested(this.extend({ 'nonce': nonce }, params));
|
|
2788
|
+
}
|
|
2789
|
+
const auth = this.encode(nonce + body);
|
|
2790
|
+
const hash = this.hash(auth, sha256.sha256, 'binary');
|
|
2791
|
+
const binary = this.encode(url);
|
|
2792
|
+
const binhash = this.binaryConcat(binary, hash);
|
|
2793
|
+
const secret = this.base64ToBinary(this.secret);
|
|
2794
|
+
const signature = this.hmac(binhash, secret, sha512.sha512, 'base64');
|
|
2795
|
+
headers = {
|
|
2796
|
+
'API-Key': this.apiKey,
|
|
2797
|
+
'API-Sign': signature,
|
|
2798
|
+
// 'Content-Type': 'application/x-www-form-urlencoded',
|
|
2799
|
+
};
|
|
2800
|
+
if (isCancelOrderBatch) {
|
|
2801
|
+
headers['Content-Type'] = 'application/json';
|
|
2802
|
+
}
|
|
2803
|
+
else {
|
|
2804
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
else {
|
|
2808
|
+
url = '/' + path;
|
|
2809
|
+
}
|
|
2810
|
+
url = this.urls['api'][api] + url;
|
|
2811
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
|
2812
|
+
}
|
|
2813
|
+
nonce() {
|
|
2814
|
+
return this.milliseconds();
|
|
2815
|
+
}
|
|
2816
|
+
handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
|
2817
|
+
if (code === 520) {
|
|
2818
|
+
throw new errors.ExchangeNotAvailable(this.id + ' ' + code.toString() + ' ' + reason);
|
|
2819
|
+
}
|
|
2820
|
+
// todo: rewrite this for "broad" exceptions matching
|
|
2821
|
+
if (body.indexOf('Invalid order') >= 0) {
|
|
2822
|
+
throw new errors.InvalidOrder(this.id + ' ' + body);
|
|
2823
|
+
}
|
|
2824
|
+
if (body.indexOf('Invalid nonce') >= 0) {
|
|
2825
|
+
throw new errors.InvalidNonce(this.id + ' ' + body);
|
|
2826
|
+
}
|
|
2827
|
+
if (body.indexOf('Insufficient funds') >= 0) {
|
|
2828
|
+
throw new errors.InsufficientFunds(this.id + ' ' + body);
|
|
2829
|
+
}
|
|
2830
|
+
if (body.indexOf('Cancel pending') >= 0) {
|
|
2831
|
+
throw new errors.CancelPending(this.id + ' ' + body);
|
|
2832
|
+
}
|
|
2833
|
+
if (body.indexOf('Invalid arguments:volume') >= 0) {
|
|
2834
|
+
throw new errors.InvalidOrder(this.id + ' ' + body);
|
|
2835
|
+
}
|
|
2836
|
+
if (body.indexOf('Rate limit exceeded') >= 0) {
|
|
2837
|
+
throw new errors.RateLimitExceeded(this.id + ' ' + body);
|
|
2838
|
+
}
|
|
2839
|
+
if (response === undefined) {
|
|
2840
|
+
return undefined;
|
|
2841
|
+
}
|
|
2842
|
+
if (body[0] === '{') {
|
|
2843
|
+
if (typeof response !== 'string') {
|
|
2844
|
+
if ('error' in response) {
|
|
2845
|
+
const numErrors = response['error'].length;
|
|
2846
|
+
if (numErrors) {
|
|
2847
|
+
const message = this.id + ' ' + body;
|
|
2848
|
+
for (let i = 0; i < response['error'].length; i++) {
|
|
2849
|
+
const error = response['error'][i];
|
|
2850
|
+
this.throwExactlyMatchedException(this.exceptions, error, message);
|
|
2851
|
+
}
|
|
2852
|
+
throw new errors.ExchangeError(message);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
return undefined;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
module.exports = kraken;
|