@proton/ccxt
Version:
A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges
1,099 lines (1,097 loc) • 177 kB
JavaScript
// ----------------------------------------------------------------------------
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
// ---------------------------------------------------------------------------
import Exchange from './abstract/kucoin.js';
import { ExchangeError, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, InvalidNonce, NotSupported, BadRequest, AuthenticationError, BadSymbol, RateLimitExceeded, PermissionDenied, InvalidAddress, ArgumentsRequired } from './base/errors.js';
import { Precise } from './base/Precise.js';
import { TICK_SIZE } from './base/functions/number.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
// ---------------------------------------------------------------------------
export default class kucoin extends Exchange {
describe() {
return this.deepExtend(super.describe(), {
'id': 'kucoin',
'name': 'KuCoin',
'countries': ['SC'],
// note "only some endpoints are rate-limited"
// so I set the 'ratelimit' on those which supposedly 'arent ratelimited'
// to the limit of the cheapest endpoint
// 60 requests in 3 seconds = 20 requests per second => ( 1000ms / 20 ) = 50 ms between requests on average
'rateLimit': 50,
'version': 'v2',
'certified': true,
'pro': true,
'comment': 'Platform 2.0',
'quoteJsonNumbers': false,
'has': {
'CORS': undefined,
'spot': true,
'margin': true,
'swap': false,
'future': false,
'option': undefined,
'borrowMargin': true,
'cancelAllOrders': true,
'cancelOrder': true,
'createDepositAddress': true,
'createOrder': true,
'createStopLimitOrder': true,
'createStopMarketOrder': true,
'createStopOrder': true,
'editOrder': true,
'fetchAccounts': true,
'fetchBalance': true,
'fetchBorrowInterest': true,
'fetchBorrowRate': false,
'fetchBorrowRateHistories': false,
'fetchBorrowRateHistory': true,
'fetchBorrowRates': false,
'fetchClosedOrders': true,
'fetchCurrencies': true,
'fetchDepositAddress': true,
'fetchDepositAddressesByNetwork': true,
'fetchDeposits': true,
'fetchDepositWithdrawFee': true,
'fetchDepositWithdrawFees': true,
'fetchFundingHistory': false,
'fetchFundingRate': false,
'fetchFundingRateHistory': false,
'fetchFundingRates': false,
'fetchIndexOHLCV': false,
'fetchL3OrderBook': true,
'fetchLedger': true,
'fetchMarginMode': false,
'fetchMarkets': true,
'fetchMarkOHLCV': false,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterestHistory': false,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrdersByStatus': true,
'fetchOrderTrades': true,
'fetchPositionMode': false,
'fetchPremiumIndexOHLCV': false,
'fetchStatus': true,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': true,
'fetchTradingFees': false,
'fetchTransactionFee': true,
'fetchWithdrawals': true,
'repayMargin': true,
'setMarginMode': false,
'transfer': true,
'withdraw': true,
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/51840849/87295558-132aaf80-c50e-11ea-9801-a2fb0c57c799.jpg',
'referral': 'https://www.kucoin.com/ucenter/signup?rcode=E5wkqe',
'api': {
'public': 'https://api.kucoin.com',
'private': 'https://api.kucoin.com',
'futuresPrivate': 'https://api-futures.kucoin.com',
'futuresPublic': 'https://api-futures.kucoin.com',
},
'test': {
'public': 'https://openapi-sandbox.kucoin.com',
'private': 'https://openapi-sandbox.kucoin.com',
'futuresPrivate': 'https://api-sandbox-futures.kucoin.com',
'futuresPublic': 'https://api-sandbox-futures.kucoin.com',
},
'www': 'https://www.kucoin.com',
'doc': [
'https://docs.kucoin.com',
],
},
'requiredCredentials': {
'apiKey': true,
'secret': true,
'password': true,
},
'api': {
'public': {
'get': {
'timestamp': 1,
'status': 1,
'symbols': 1,
'markets': 1,
'market/allTickers': 1,
'market/orderbook/level{level}_{limit}': 1,
'market/orderbook/level2_20': 1,
'market/orderbook/level2_100': 1,
'market/histories': 1,
'market/candles': 1,
'market/stats': 1,
'currencies': 1,
'currencies/{currency}': 1,
'prices': 1,
'mark-price/{symbol}/current': 1,
'margin/config': 1,
'margin/trade/last': 1,
},
'post': {
'bullet-public': 1,
},
},
'private': {
'get': {
'market/orderbook/level{level}': 1,
'market/orderbook/level2': { 'v3': 2 },
'market/orderbook/level3': 1,
'accounts': 1,
'accounts/{accountId}': 1,
// 'accounts/{accountId}/ledgers': 1, Deprecated endpoint
'accounts/ledgers': 3.333,
'accounts/{accountId}/holds': 1,
'accounts/transferable': 1,
'base-fee': 1,
'sub/user': 1,
'user-info': 1,
'sub/api-key': 1,
'sub-accounts': 1,
'sub-accounts/{subUserId}': 1,
'deposit-addresses': 1,
'deposits': 10,
'hist-deposits': 10,
// 'hist-orders': 1, Deprecated endpoint
'hist-withdrawals': 10,
'withdrawals': 10,
'withdrawals/quotas': 1,
'orders': 2,
'order/client-order/{clientOid}': 1,
'orders/{orderId}': 1,
'limit/orders': 1,
'fills': 6.66667,
'limit/fills': 1,
'isolated/accounts': 2,
'isolated/account/{symbol}': 2,
'isolated/borrow/outstanding': 2,
'isolated/borrow/repaid': 2,
'isolated/symbols': 2,
'margin/account': 1,
'margin/borrow': 1,
'margin/borrow/outstanding': 1,
'margin/borrow/repaid': 1,
'margin/lend/active': 1,
'margin/lend/done': 1,
'margin/lend/trade/unsettled': 1,
'margin/lend/trade/settled': 1,
'margin/lend/assets': 1,
'margin/market': 1,
'stop-order/{orderId}': 1,
'stop-order': 1,
'stop-order/queryOrderByClientOid': 1,
'trade-fees': 1.3333,
'hf/accounts/ledgers': 3.33,
'hf/orders/active': 2,
'hf/orders/active/symbols': 20,
'hf/orders/done': 2,
'hf/orders/{orderId}': 1,
'hf/orders/client-order/{clientOid}': 2,
'hf/fills': 6.67, // 9 times/3s = 3/s => cost = 20 / 3 = 6.67
},
'post': {
'accounts': 1,
'accounts/inner-transfer': { 'v2': 1 },
'accounts/sub-transfer': { 'v2': 25 },
'deposit-addresses': 1,
'withdrawals': 1,
'orders': 4,
'orders/multi': 20,
'isolated/borrow': 2,
'isolated/repay/all': 2,
'isolated/repay/single': 2,
'margin/borrow': 1,
'margin/order': 1,
'margin/repay/all': 1,
'margin/repay/single': 1,
'margin/lend': 1,
'margin/toggle-auto-lend': 1,
'bullet-private': 1,
'stop-order': 1,
'sub/user': 1,
'sub/api-key': 1,
'sub/api-key/update': 1,
'hf/orders': 0.4,
'hf/orders/sync': 1.33,
'hf/orders/multi': 20,
'hf/orders/multi/sync': 20,
'hf/orders/alter': 1, // 60 times/3s = 20/s => cost = 20/20 = 1
},
'delete': {
'withdrawals/{withdrawalId}': 1,
'orders': 20,
'order/client-order/{clientOid}': 1,
'orders/{orderId}': 1,
'margin/lend/{orderId}': 1,
'stop-order/cancelOrderByClientOid': 1,
'stop-order/{orderId}': 1,
'stop-order/cancel': 1,
'sub/api-key': 1,
'hf/orders/{orderId}': 0.4,
'hf/orders/sync/{orderId}': 0.4,
'hf/orders/client-order/{clientOid}': 0.4,
'hf/orders/sync/client-order/{clientOid}': 0.4,
'hf/orders/cancel/{orderId}': 1,
'hf/orders': 20, // 3 times/3s = 1/s => cost = 20 / 1 = 20
},
},
'futuresPublic': {
// cheapest futures 'limited' endpoint is 40 requests per 3 seconds = 14.333 per second => cost = 20/14.333 = 1.3953
'get': {
'contracts/active': 1.3953,
'contracts/{symbol}': 1.3953,
'ticker': 1.3953,
'level2/snapshot': 2,
'level2/depth20': 1.3953,
'level2/depth100': 1.3953,
'level2/message/query': 1.3953,
'level3/message/query': 1.3953,
'level3/snapshot': 1.3953,
'trade/history': 1.3953,
'interest/query': 1.3953,
'index/query': 1.3953,
'mark-price/{symbol}/current': 1.3953,
'premium/query': 1.3953,
'funding-rate/{symbol}/current': 1.3953,
'timestamp': 1.3953,
'status': 1.3953,
'kline/query': 1.3953,
},
'post': {
'bullet-public': 1.3953,
},
},
'futuresPrivate': {
'get': {
'account-overview': 2,
'transaction-history': 6.666,
'deposit-address': 1.3953,
'deposit-list': 1.3953,
'withdrawals/quotas': 1.3953,
'withdrawal-list': 1.3953,
'transfer-list': 1.3953,
'orders': 1.3953,
'stopOrders': 1.3953,
'recentDoneOrders': 1.3953,
'orders/{orderId}': 1.3953,
'orders/byClientOid': 1.3953,
'fills': 6.666,
'recentFills': 6.666,
'openOrderStatistics': 1.3953,
'position': 1.3953,
'positions': 6.666,
'funding-history': 6.666, // 9 requests per 3 seconds = 3 per second => cost = 20/3 = 6.666
},
'post': {
'withdrawals': 1.3953,
'transfer-out': 1.3953,
'orders': 1.3953,
'position/margin/auto-deposit-status': 1.3953,
'position/margin/deposit-margin': 1.3953,
'bullet-private': 1.3953,
},
'delete': {
'withdrawals/{withdrawalId}': 1.3953,
'cancel/transfer-out': 1.3953,
'orders/{orderId}': 1.3953,
'orders': 6.666,
'stopOrders': 1.3953,
},
},
},
'timeframes': {
'1m': '1min',
'3m': '3min',
'5m': '5min',
'15m': '15min',
'30m': '30min',
'1h': '1hour',
'2h': '2hour',
'4h': '4hour',
'6h': '6hour',
'8h': '8hour',
'12h': '12hour',
'1d': '1day',
'1w': '1week',
},
'precisionMode': TICK_SIZE,
'exceptions': {
'exact': {
'order not exist': OrderNotFound,
'order not exist.': OrderNotFound,
'order_not_exist': OrderNotFound,
'order_not_exist_or_not_allow_to_cancel': InvalidOrder,
'Order size below the minimum requirement.': InvalidOrder,
'The withdrawal amount is below the minimum requirement.': ExchangeError,
'Unsuccessful! Exceeded the max. funds out-transfer limit': InsufficientFunds,
'400': BadRequest,
'401': AuthenticationError,
'403': NotSupported,
'404': NotSupported,
'405': NotSupported,
'429': RateLimitExceeded,
'500': ExchangeNotAvailable,
'503': ExchangeNotAvailable,
'101030': PermissionDenied,
'103000': InvalidOrder,
'200004': InsufficientFunds,
'210014': InvalidOrder,
'210021': InsufficientFunds,
'230003': InsufficientFunds,
'260000': InvalidAddress,
'260100': InsufficientFunds,
'300000': InvalidOrder,
'400000': BadSymbol,
'400001': AuthenticationError,
'400002': InvalidNonce,
'400003': AuthenticationError,
'400004': AuthenticationError,
'400005': AuthenticationError,
'400006': AuthenticationError,
'400007': AuthenticationError,
'400008': NotSupported,
'400100': BadRequest,
'400200': InvalidOrder,
'400350': InvalidOrder,
'400370': InvalidOrder,
'400500': InvalidOrder,
'400600': BadSymbol,
'400760': InvalidOrder,
'401000': BadRequest,
'411100': AccountSuspended,
'415000': BadRequest,
'500000': ExchangeNotAvailable,
'260220': InvalidAddress,
'900014': BadRequest, // {"code":"900014","msg":"Invalid chainId"}
},
'broad': {
'Exceeded the access frequency': RateLimitExceeded,
'require more permission': PermissionDenied,
},
},
'fees': {
'trading': {
'tierBased': true,
'percentage': true,
'taker': this.parseNumber('0.001'),
'maker': this.parseNumber('0.001'),
'tiers': {
'taker': [
[this.parseNumber('0'), this.parseNumber('0.001')],
[this.parseNumber('50'), this.parseNumber('0.001')],
[this.parseNumber('200'), this.parseNumber('0.0009')],
[this.parseNumber('500'), this.parseNumber('0.0008')],
[this.parseNumber('1000'), this.parseNumber('0.0007')],
[this.parseNumber('2000'), this.parseNumber('0.0007')],
[this.parseNumber('4000'), this.parseNumber('0.0006')],
[this.parseNumber('8000'), this.parseNumber('0.0005')],
[this.parseNumber('15000'), this.parseNumber('0.00045')],
[this.parseNumber('25000'), this.parseNumber('0.0004')],
[this.parseNumber('40000'), this.parseNumber('0.00035')],
[this.parseNumber('60000'), this.parseNumber('0.0003')],
[this.parseNumber('80000'), this.parseNumber('0.00025')],
],
'maker': [
[this.parseNumber('0'), this.parseNumber('0.001')],
[this.parseNumber('50'), this.parseNumber('0.0009')],
[this.parseNumber('200'), this.parseNumber('0.0007')],
[this.parseNumber('500'), this.parseNumber('0.0005')],
[this.parseNumber('1000'), this.parseNumber('0.0003')],
[this.parseNumber('2000'), this.parseNumber('0')],
[this.parseNumber('4000'), this.parseNumber('0')],
[this.parseNumber('8000'), this.parseNumber('0')],
[this.parseNumber('15000'), this.parseNumber('-0.00005')],
[this.parseNumber('25000'), this.parseNumber('-0.00005')],
[this.parseNumber('40000'), this.parseNumber('-0.00005')],
[this.parseNumber('60000'), this.parseNumber('-0.00005')],
[this.parseNumber('80000'), this.parseNumber('-0.00005')],
],
},
},
'funding': {
'tierBased': false,
'percentage': false,
'withdraw': {},
'deposit': {},
},
},
'commonCurrencies': {
'BIFI': 'BIFIF',
'EDGE': 'DADI',
'HOT': 'HOTNOW',
'TRY': 'Trias',
'VAI': 'VAIOT',
'WAX': 'WAXP',
},
'options': {
'version': 'v1',
'symbolSeparator': '-',
'fetchMyTradesMethod': 'private_get_fills',
'fetchMarkets': {
'fetchTickersFees': true,
},
'withdraw': {
'includeFee': false,
},
// endpoint versions
'versions': {
'public': {
'GET': {
'currencies/{currency}': 'v2',
'status': 'v1',
'market/orderbook/level2_20': 'v1',
'market/orderbook/level2_100': 'v1',
'market/orderbook/level{level}_{limit}': 'v1',
},
},
'private': {
'GET': {
'market/orderbook/level2': 'v3',
'market/orderbook/level3': 'v3',
'market/orderbook/level{level}': 'v3',
'deposit-addresses': 'v1',
'hf/accounts/ledgers': 'v1',
'hf/orders/active': 'v1',
'hf/orders/active/symbols': 'v1',
'hf/orders/done': 'v1',
'hf/orders/{orderId}': 'v1',
'hf/orders/client-order/{clientOid}': 'v1',
'hf/fills': 'v1',
},
'POST': {
'accounts/inner-transfer': 'v2',
'accounts/sub-transfer': 'v2',
'accounts': 'v1',
'hf/orders': 'v1',
'hf/orders/sync': 'v1',
'hf/orders/multi': 'v1',
'hf/orders/multi/sync': 'v1',
'hf/orders/alter': 'v1',
},
'DELETE': {
'hf/orders/{orderId}': 'v1',
'hf/orders/sync/{orderId}': 'v1',
'hf/orders/client-order/{clientOid}': 'v1',
'hf/orders/sync/client-order/{clientOid}': 'v1',
'hf/orders/cancel/{orderId}': 'v1',
'hf/orders': 'v1',
},
},
'futuresPrivate': {
'GET': {
'account-overview': 'v1',
'positions': 'v1',
},
'POST': {
'transfer-out': 'v2',
},
},
'futuresPublic': {
'GET': {
'level3/snapshot': 'v2',
},
},
},
'partner': {
// the support for spot and future exchanges as separate settings
'spot': {
'id': 'ccxt',
'key': '9e58cc35-5b5e-4133-92ec-166e3f077cb8',
},
'future': {
'id': 'ccxtfutures',
'key': '1b327198-f30c-4f14-a0ac-918871282f15',
},
// exchange-wide settings are also supported
// 'id': 'ccxt'
// 'key': '9e58cc35-5b5e-4133-92ec-166e3f077cb8',
},
'accountsByType': {
'spot': 'trade',
'margin': 'margin',
'cross': 'margin',
'isolated': 'isolated',
'main': 'main',
'funding': 'main',
'future': 'contract',
'swap': 'contract',
'mining': 'pool',
'hf': 'trade_hf',
},
'networks': {
'Native': 'bech32',
'BTC-Segwit': 'btc',
'ERC20': 'eth',
'BEP20': 'bsc',
'TRC20': 'trx',
'TERRA': 'luna',
'BNB': 'bsc',
'HRC20': 'heco',
'HT': 'heco',
},
'networksById': {
'BEP20': 'BSC',
},
'marginModes': {
'cross': 'MARGIN_TRADE',
'isolated': 'MARGIN_ISOLATED_TRADE',
'spot': 'TRADE',
},
},
});
}
nonce() {
return this.milliseconds();
}
async fetchTime(params = {}) {
/**
* @method
* @name kucoin#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @param {object} params extra parameters specific to the kucoin api endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
const response = await this.publicGetTimestamp(params);
//
// {
// "code":"200000",
// "msg":"success",
// "data":1546837113087
// }
//
return this.safeInteger(response, 'data');
}
async fetchStatus(params = {}) {
/**
* @method
* @name kucoin#fetchStatus
* @description the latest known information on the availability of the exchange API
* @param {object} params extra parameters specific to the kucoin api endpoint
* @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
*/
const response = await this.publicGetStatus(params);
//
// {
// "code":"200000",
// "data":{
// "status":"open", //open, close, cancelonly
// "msg":"upgrade match engine" //remark for operation
// }
// }
//
const data = this.safeValue(response, 'data', {});
const status = this.safeString(data, 'status');
return {
'status': (status === 'open') ? 'ok' : 'maintenance',
'updated': undefined,
'eta': undefined,
'url': undefined,
'info': response,
};
}
async fetchMarkets(params = {}) {
/**
* @method
* @name kucoin#fetchMarkets
* @description retrieves data on all markets for kucoin
* @param {object} params extra parameters specific to the exchange api endpoint
* @returns {[object]} an array of objects representing market data
*/
const response = await this.publicGetSymbols(params);
//
// {
// "code": "200000",
// "data": [
// {
// "symbol": "XLM-USDT",
// "name": "XLM-USDT",
// "baseCurrency": "XLM",
// "quoteCurrency": "USDT",
// "feeCurrency": "USDT",
// "market": "USDS",
// "baseMinSize": "0.1",
// "quoteMinSize": "0.01",
// "baseMaxSize": "10000000000",
// "quoteMaxSize": "99999999",
// "baseIncrement": "0.0001",
// "quoteIncrement": "0.000001",
// "priceIncrement": "0.000001",
// "priceLimitRate": "0.1",
// "isMarginEnabled": true,
// "enableTrading": true
// },
// ]
// }
//
const data = this.safeValue(response, 'data');
const options = this.safeValue(this.options, 'fetchMarkets', {});
const fetchTickersFees = this.safeValue(options, 'fetchTickersFees', true);
let tickersResponse = {};
if (fetchTickersFees) {
tickersResponse = await this.publicGetMarketAllTickers(params);
}
//
// {
// "code": "200000",
// "data": {
// "time":1602832092060,
// "ticker":[
// {
// "symbol": "BTC-USDT", // symbol
// "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
// "buy": "11328.9", // bestAsk
// "sell": "11329", // bestBid
// "changeRate": "-0.0055", // 24h change rate
// "changePrice": "-63.6", // 24h change price
// "high": "11610", // 24h highest price
// "low": "11200", // 24h lowest price
// "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
// "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
// "last": "11328.9", // last price
// "averagePrice": "11360.66065903", // 24h average transaction price yesterday
// "takerFeeRate": "0.001", // Basic Taker Fee
// "makerFeeRate": "0.001", // Basic Maker Fee
// "takerCoefficient": "1", // Taker Fee Coefficient
// "makerCoefficient": "1" // Maker Fee Coefficient
// }
// ]
// }
// }
//
const tickersData = this.safeValue(tickersResponse, 'data', {});
const tickers = this.safeValue(tickersData, 'ticker', []);
const tickersByMarketId = this.indexBy(tickers, 'symbol');
const result = [];
for (let i = 0; i < data.length; i++) {
const market = data[i];
const id = this.safeString(market, 'symbol');
const [baseId, quoteId] = id.split('-');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
// const quoteIncrement = this.safeNumber (market, 'quoteIncrement');
const ticker = this.safeValue(tickersByMarketId, id, {});
const makerFeeRate = this.safeString(ticker, 'makerFeeRate');
const takerFeeRate = this.safeString(ticker, 'takerFeeRate');
const makerCoefficient = this.safeString(ticker, 'makerCoefficient');
const takerCoefficient = this.safeString(ticker, 'takerCoefficient');
result.push({
'id': id,
'symbol': base + '/' + quote,
'base': base,
'quote': quote,
'settle': undefined,
'baseId': baseId,
'quoteId': quoteId,
'settleId': undefined,
'type': 'spot',
'spot': true,
'margin': this.safeValue(market, 'isMarginEnabled'),
'swap': false,
'future': false,
'option': false,
'active': this.safeValue(market, 'enableTrading'),
'contract': false,
'linear': undefined,
'inverse': undefined,
'taker': this.parseNumber(Precise.stringMul(takerFeeRate, takerCoefficient)),
'maker': this.parseNumber(Precise.stringMul(makerFeeRate, makerCoefficient)),
'contractSize': undefined,
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.safeNumber(market, 'baseIncrement'),
'price': this.safeNumber(market, 'priceIncrement'),
},
'limits': {
'leverage': {
'min': undefined,
'max': undefined,
},
'amount': {
'min': this.safeNumber(market, 'baseMinSize'),
'max': this.safeNumber(market, 'baseMaxSize'),
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': this.safeNumber(market, 'quoteMinSize'),
'max': this.safeNumber(market, 'quoteMaxSize'),
},
},
'info': market,
});
}
return result;
}
async fetchCurrencies(params = {}) {
/**
* @method
* @name kucoin#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://docs.kucoin.com/#get-currencies
* @param {object} params extra parameters specific to the kucoin api endpoint
* @returns {object} an associative dictionary of currencies
*/
const response = await this.publicGetCurrencies(params);
//
// {
// "currency": "OMG",
// "name": "OMG",
// "fullName": "OmiseGO",
// "precision": 8,
// "confirms": 12,
// "withdrawalMinSize": "4",
// "withdrawalMinFee": "1.25",
// "isWithdrawEnabled": false,
// "isDepositEnabled": false,
// "isMarginEnabled": false,
// "isDebitEnabled": false
// }
//
const data = this.safeValue(response, 'data', []);
const result = {};
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const id = this.safeString(entry, 'currency');
const name = this.safeString(entry, 'fullName');
const code = this.safeCurrencyCode(id);
const isWithdrawEnabled = this.safeValue(entry, 'isWithdrawEnabled', false);
const isDepositEnabled = this.safeValue(entry, 'isDepositEnabled', false);
const fee = this.safeNumber(entry, 'withdrawalMinFee');
const active = (isWithdrawEnabled && isDepositEnabled);
result[code] = {
'id': id,
'name': name,
'code': code,
'precision': this.parseNumber(this.parsePrecision(this.safeString(entry, 'precision'))),
'info': entry,
'active': active,
'deposit': isDepositEnabled,
'withdraw': isWithdrawEnabled,
'fee': fee,
'limits': this.limits,
'networks': {},
};
}
return result;
}
async fetchAccounts(params = {}) {
/**
* @method
* @name kucoin#fetchAccounts
* @description fetch all the accounts associated with a profile
* @param {object} params extra parameters specific to the kucoin api endpoint
* @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
*/
const response = await this.privateGetAccounts(params);
//
// {
// code: "200000",
// data: [
// {
// balance: "0.00009788",
// available: "0.00009788",
// holds: "0",
// currency: "BTC",
// id: "5c6a4fd399a1d81c4f9cc4d0",
// type: "trade"
// },
// {
// balance: "0.00000001",
// available: "0.00000001",
// holds: "0",
// currency: "ETH",
// id: "5c6a49ec99a1d819392e8e9f",
// type: "trade"
// }
// ]
// }
//
const data = this.safeValue(response, 'data', []);
const result = [];
for (let i = 0; i < data.length; i++) {
const account = data[i];
const accountId = this.safeString(account, 'id');
const currencyId = this.safeString(account, 'currency');
const code = this.safeCurrencyCode(currencyId);
const type = this.safeString(account, 'type'); // main or trade
result.push({
'id': accountId,
'type': type,
'currency': code,
'info': account,
});
}
return result;
}
async fetchTransactionFee(code, params = {}) {
/**
* @method
* @name kucoin#fetchTransactionFee
* @description *DEPRECATED* please use fetchDepositWithdrawFee instead
* @see https://docs.kucoin.com/#get-withdrawal-quotas
* @param {string} code unified currency code
* @param {object} params extra parameters specific to the kucoin api endpoint
* @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
*/
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'currency': currency['id'],
};
const networks = this.safeValue(this.options, 'networks', {});
let network = this.safeStringUpper2(params, 'network', 'chain');
network = this.safeStringLower(networks, network, network);
if (network !== undefined) {
network = network.toLowerCase();
request['chain'] = network.toLowerCase();
params = this.omit(params, ['network', 'chain']);
}
const response = await this.privateGetWithdrawalsQuotas(this.extend(request, params));
const data = response['data'];
const withdrawFees = {};
withdrawFees[code] = this.safeNumber(data, 'withdrawMinFee');
return {
'info': response,
'withdraw': withdrawFees,
'deposit': {},
};
}
async fetchDepositWithdrawFee(code, params = {}) {
/**
* @method
* @name kucoin#fetchDepositWithdrawFee
* @description fetch the fee for deposits and withdrawals
* @see https://docs.kucoin.com/#get-withdrawal-quotas
* @param {string} code unified currency code
* @param {object} params extra parameters specific to the kucoin api endpoint
* @param {string|undefined} params.network The chain of currency. This only apply for multi-chain currency, and there is no need for single chain currency; you can query the chain through the response of the GET /api/v2/currencies/{currency} interface
* @returns {object} a [fee structure]{@link https://docs.ccxt.com/#/?id=fee-structure}
*/
await this.loadMarkets();
const currency = this.currency(code);
const request = {
'currency': currency['id'],
};
const networkCode = this.safeStringUpper(params, 'network');
const network = this.networkCodeToId(networkCode, code);
if (network !== undefined) {
request['chain'] = network.toLowerCase();
params = this.omit(params, ['network']);
}
const response = await this.privateGetWithdrawalsQuotas(this.extend(request, params));
//
// {
// "code": "200000",
// "data": {
// "currency": "USDT",
// "limitBTCAmount": "1.00000000",
// "usedBTCAmount": "0.00000000",
// "remainAmount": "16548.072149",
// "availableAmount": "0",
// "withdrawMinFee": "25",
// "innerWithdrawMinFee": "0",
// "withdrawMinSize": "50",
// "isWithdrawEnabled": true,
// "precision": 6,
// "chain": "ERC20"
// }
// }
//
const data = this.safeValue(response, 'data');
return this.parseDepositWithdrawFee(data, currency);
}
parseDepositWithdrawFee(fee, currency = undefined) {
//
// {
// "currency": "USDT",
// "limitBTCAmount": "1.00000000",
// "usedBTCAmount": "0.00000000",
// "remainAmount": "16548.072149",
// "availableAmount": "0",
// "withdrawMinFee": "25",
// "innerWithdrawMinFee": "0",
// "withdrawMinSize": "50",
// "isWithdrawEnabled": true,
// "precision": 6,
// "chain": "ERC20"
// }
//
const result = {
'info': fee,
'withdraw': {
'fee': undefined,
'percentage': undefined,
},
'deposit': {
'fee': undefined,
'percentage': undefined,
},
'networks': {},
};
const isWithdrawEnabled = this.safeValue(fee, 'isWithdrawEnabled');
if (isWithdrawEnabled) {
result['withdraw']['fee'] = this.safeNumber(fee, 'withdrawalMinFee');
result['withdraw']['percentage'] = false;
const networkId = this.safeString(fee, 'chain');
if (networkId) {
const networkCode = this.networkIdToCode(networkId, this.safeString(currency, 'code'));
result['networks'][networkCode] = {
'withdraw': result['withdraw'],
'deposit': {
'fee': undefined,
'percentage': undefined,
},
};
}
}
return result;
}
isFuturesMethod(methodName, params) {
//
// Helper
// @methodName (string): The name of the method
// @params (dict): The parameters passed into {methodName}
// @return: true if the method used is meant for futures trading, false otherwise
//
const defaultType = this.safeString2(this.options, methodName, 'defaultType', 'trade');
const requestedType = this.safeString(params, 'type', defaultType);
const accountsByType = this.safeValue(this.options, 'accountsByType');
const type = this.safeString(accountsByType, requestedType);
if (type === undefined) {
const keys = Object.keys(accountsByType);
throw new ExchangeError(this.id + ' isFuturesMethod() type must be one of ' + keys.join(', '));
}
params = this.omit(params, 'type');
return (type === 'contract') || (type === 'future') || (type === 'futures'); // * (type === 'futures') deprecated, use (type === 'future')
}
parseTicker(ticker, market = undefined) {
//
// {
// "symbol": "BTC-USDT", // symbol
// "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
// "buy": "11328.9", // bestAsk
// "sell": "11329", // bestBid
// "changeRate": "-0.0055", // 24h change rate
// "changePrice": "-63.6", // 24h change price
// "high": "11610", // 24h highest price
// "low": "11200", // 24h lowest price
// "vol": "2282.70993217", // 24h volume,the aggregated trading volume in BTC
// "volValue": "25984946.157790431", // 24h total, the trading volume in quote currency of last 24 hours
// "last": "11328.9", // last price
// "averagePrice": "11360.66065903", // 24h average transaction price yesterday
// "takerFeeRate": "0.001", // Basic Taker Fee
// "makerFeeRate": "0.001", // Basic Maker Fee
// "takerCoefficient": "1", // Taker Fee Coefficient
// "makerCoefficient": "1" // Maker Fee Coefficient
// }
//
// {
// "trading": true,
// "symbol": "KCS-BTC",
// "buy": 0.00011,
// "sell": 0.00012,
// "sort": 100,
// "volValue": 3.13851792584, //total
// "baseCurrency": "KCS",
// "market": "BTC",
// "quoteCurrency": "BTC",
// "symbolCode": "KCS-BTC",
// "datetime": 1548388122031,
// "high": 0.00013,
// "vol": 27514.34842,
// "low": 0.0001,
// "changePrice": -1.0e-5,
// "changeRate": -0.0769,
// "lastTradedPrice": 0.00012,
// "board": 0,
// "mark": 0
// }
//
// market/ticker ws subscription
//
// {
// bestAsk: '62258.9',
// bestAskSize: '0.38579986',
// bestBid: '62258.8',
// bestBidSize: '0.0078381',
// price: '62260.7',
// sequence: '1621383297064',
// size: '0.00002841',
// time: 1634641777363
// }
//
let percentage = this.safeString(ticker, 'changeRate');
if (percentage !== undefined) {
percentage = Precise.stringMul(percentage, '100');
}
let last = this.safeString2(ticker, 'last', 'lastTradedPrice');
last = this.safeString(ticker, 'price', last);
const marketId = this.safeString(ticker, 'symbol');
market = this.safeMarket(marketId, market, '-');
const symbol = market['symbol'];
const baseVolume = this.safeString(ticker, 'vol');
const quoteVolume = this.safeString(ticker, 'volValue');
const timestamp = this.safeInteger2(ticker, 'time', 'datetime');
return this.safeTicker({
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString(ticker, 'high'),
'low': this.safeString(ticker, 'low'),
'bid': this.safeString2(ticker, 'buy', 'bestBid'),
'bidVolume': this.safeString(ticker, 'bestBidSize'),
'ask': this.safeString2(ticker, 'sell', 'bestAsk'),
'askVolume': this.safeString(ticker, 'bestAskSize'),
'vwap': undefined,
'open': this.safeString(ticker, 'open'),
'close': last,
'last': last,
'previousClose': undefined,
'change': this.safeString(ticker, 'changePrice'),
'percentage': percentage,
'average': this.safeString(ticker, 'averagePrice'),
'baseVolume': baseVolume,
'quoteVolume': quoteVolume,
'info': ticker,
}, market);
}
async fetchTickers(symbols = undefined, params = {}) {
/**
* @method
* @name kucoin#fetchTickers
* @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
* @param {[string]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} params extra parameters specific to the kucoin api endpoint
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
await this.loadMarkets();
symbols = this.marketSymbols(symbols);
const response = await this.publicGetMarketAllTickers(params);
//
// {
// "code": "200000",
// "data": {
// "time":1602832092060,
// "ticker":[
// {
// "symbol": "BTC-USDT", // symbol
// "symbolName":"BTC-USDT", // Name of trading pairs, it would change after renaming
// "buy": "11328.9", // bestAsk
// "sell": "11329", // bestBid
// "changeRate": "-0.0055", // 24h change rate
// "changePrice": "-63.6", // 24h change price
// "high": "11610", // 24h highest price
// "low": "11200", // 24h lowest price
// "vol": "2282.70993217", // 24h