ccxt-compiled
Version:
A JavaScript / Python / PHP cryptocurrency trading library with support for 90+ exchanges
861 lines (691 loc) • 32.5 kB
JavaScript
"use strict";
//-----------------------------------------------------------------------------
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _values = require('babel-runtime/core-js/object/values');
var _values2 = _interopRequireDefault(_values);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _entries = require('babel-runtime/core-js/object/entries');
var _entries2 = _interopRequireDefault(_entries);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const isNode = typeof window === 'undefined',
functions = require('./functions'),
throttle = require('./throttle'),
fetch = require('fetch-ponyfill')().fetch,
Market = require('./Market');
const { deepExtend,
extend,
sleep,
timeout,
flatten,
indexBy,
sortBy,
groupBy,
aggregate,
uuid,
precisionFromString } = functions;
const { ExchangeError,
NotSupported,
AuthenticationError,
DDoSProtection,
RequestTimeout,
ExchangeNotAvailable } = require('./errors');
// stub until we get a better solution for Webpack and React
// const journal = isNode && require ('./journal')
const journal = undefined;
module.exports = class Exchange {
getMarket(symbol) {
if (!this.marketClasses) this.marketClasses = {};
let marketClass = this.marketClasses[symbol];
if (marketClass) return marketClass;
marketClass = new Market(this, symbol);
this.marketClasses[symbol] = marketClass; // only one Market instance per market
return marketClass;
}
describe() {
return {};
}
constructor(userConfig = {}) {
(0, _assign2.default)(this, functions, { encode: string => string, decode: string => string });
if (isNode) this.nodeVersion = process.version.match(/\d+\.\d+.\d+/)[0];
// this.initRestRateLimiter ()
// if (isNode) {
// this.userAgent = {
// 'User-Agent': 'ccxt/' + Exchange.ccxtVersion +
// ' (+https://github.com/ccxt/ccxt)' +
// ' Node.js/' + this.nodeVersion + ' (JavaScript)'
// }
// }
this.userAgents = {
'chrome': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
'chrome39': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36'
};
this.headers = {};
// prepended to URL, like https://proxy.com/https://exchange.com/api...
this.proxy = '';
this.iso8601 = timestamp => new Date(timestamp).toISOString();
this.parse8601 = x => Date.parse(x.indexOf('+') >= 0 || x.slice(-1) == 'Z' ? x : x + 'Z');
this.milliseconds = Date.now;
this.microseconds = () => Math.floor(this.milliseconds() * 1000);
this.seconds = () => Math.floor(this.milliseconds() / 1000);
this.id = undefined;
// rate limiter settings
this.enableRateLimit = false;
this.rateLimit = 2000; // milliseconds = seconds * 1000
this.parseJsonResponse = true; // whether a reply is required to be in JSON or not
this.substituteCommonCurrencyCodes = true; // reserved
this.parseBalanceFromOpenOrders = false; // some exchanges return balance updates from order API endpoints
this.timeout = 10000; // milliseconds
this.verbose = false;
this.debug = false;
this.journal = 'debug.json';
this.userAgent = undefined;
this.twofa = false; // two-factor authentication (2FA)
this.timeframes = undefined;
this.hasPublicAPI = true;
this.hasPrivateAPI = true;
this.hasCORS = false;
this.hasDeposit = false;
this.hasFetchBalance = true;
this.hasFetchClosedOrders = false;
this.hasFetchCurrencies = false;
this.hasFetchMyTrades = false;
this.hasFetchOHLCV = false;
this.hasFetchOpenOrders = false;
this.hasFetchOrder = false;
this.hasFetchOrderBook = true;
this.hasFetchOrders = false;
this.hasFetchTicker = true;
this.hasFetchTickers = false;
this.hasFetchTrades = true;
this.hasWithdraw = false;
this.hasCreateOrder = this.hasPrivateAPI;
this.hasCancelOrder = this.hasPrivateAPI;
this.requiredCredentials = {
'apiKey': true,
'secret': true,
'uid': false,
'login': false,
'password': false
};
this.balance = {};
this.orderbooks = {};
this.tickers = {};
this.fees = {};
this.orders = {};
this.trades = {};
this.currencies = {};
this.last_http_response = undefined;
this.last_json_response = undefined;
this.arrayConcat = (a, b) => a.concat(b);
// TODO: generate
this.market_id = this.marketId;
this.market_ids = this.marketIds;
this.array_concat = this.arrayConcat;
this.implode_params = this.implodeParams;
this.extract_params = this.extractParams;
this.fetch_balance = this.fetchBalance;
this.fetch_free_balance = this.fetchFreeBalance;
this.fetch_used_balance = this.fetchUsedBalance;
this.fetch_total_balance = this.fetchTotalBalance;
this.fetch_l2_order_book = this.fetchL2OrderBook;
this.fetch_order_book = this.fetchOrderBook;
this.fetch_tickers = this.fetchTickers;
this.fetch_ticker = this.fetchTicker;
this.fetch_trades = this.fetchTrades;
this.fetch_order = this.fetchOrder;
this.fetch_orders = this.fetchOrders;
this.fetch_open_orders = this.fetchOpenOrders;
this.fetch_closed_orders = this.fetchClosedOrders;
this.fetch_order_status = this.fetchOrderStatus;
this.fetch_markets = this.fetchMarkets;
this.load_markets = this.loadMarkets;
this.set_markets = this.setMarkets;
this.parse_balance = this.parseBalance;
this.parse_bid_ask = this.parseBidAsk;
this.parse_bids_asks = this.parseBidsAsks;
this.parse_order_book = this.parseOrderBook;
this.parse_trades = this.parseTrades;
this.parse_orders = this.parseOrders;
this.parse_ohlcv = this.parseOHLCV;
this.parse_ohlcvs = this.parseOHLCVs;
this.edit_limit_buy_order = this.editLimitBuyOrder;
this.edit_limit_sell_order = this.editLimitSellOrder;
this.edit_limit_order = this.editLimitOrder;
this.edit_order = this.editOrder;
this.create_limit_buy_order = this.createLimitBuyOrder;
this.create_limit_sell_order = this.createLimitSellOrder;
this.create_market_buy_order = this.createMarketBuyOrder;
this.create_market_sell_order = this.createMarketSellOrder;
this.create_order = this.createOrder;
this.calculate_fee = this.calculateFee;
this.common_currency_code = this.commonCurrencyCode;
this.price_to_precision = this.priceToPrecision;
this.amount_to_precision = this.amountToPrecision;
this.fee_to_precision = this.feeToPrecision;
this.cost_to_precision = this.costToPrecision;
this.precisionFromString = precisionFromString;
this.precision_from_string = precisionFromString;
this.truncate = functions.truncate;
this.uuid = uuid;
// API methods metainfo
this.has = {
'cancelOrder': this.hasPrivateAPI,
'createDepositAddress': false,
'createOrder': this.hasPrivateAPI,
'deposit': false,
'fetchBalance': this.hasPrivateAPI,
'fetchClosedOrders': false,
'fetchCurrencies': false,
'fetchDepositAddress': false,
'fetchMarkets': true,
'fetchMyTrades': false,
'fetchOHLCV': false,
'fetchOpenOrders': false,
'fetchOrder': false,
'fetchOrderBook': true,
'fetchOrders': false,
'fetchTicker': true,
'fetchTickers': false,
'fetchTrades': true,
'withdraw': false
// merge configs
};const config = deepExtend(this.describe(), userConfig);
// merge to this
for (const [property, value] of (0, _entries2.default)(config)) this[property] = deepExtend(this[property], value);
if (this.api) this.defineRestApi(this.api, 'request');
this.initRestRateLimiter();
if (this.markets) this.setMarkets(this.markets);
if (this.debug && journal) {
journal(() => this.journal, this, (0, _keys2.default)(this.has));
}
}
defaults() {
return {/* override me */};
}
nonce() {
return this.seconds();
}
encodeURIComponent(...args) {
return encodeURIComponent(...args);
}
checkRequiredCredentials() {
(0, _keys2.default)(this.requiredCredentials).map(key => {
if (this.requiredCredentials[key] && !this[key]) throw new AuthenticationError(this.id + ' requires `' + key + '`');
});
}
initRestRateLimiter() {
this.tokenBucket = this.extend({
refillRate: 1 / this.rateLimit,
delay: 1,
capacity: 1,
defaultCost: 1,
maxCapacity: 1000
}, this.tokenBucket);
this.throttle = throttle(this.tokenBucket);
this.executeRestRequest = function (url, method = 'GET', headers = undefined, body = undefined) {
let promise = fetch(url, { 'method': method, 'headers': headers, 'body': body, 'agent': this.tunnelAgent || null, timeout: this.timeout }).catch(e => {
if (isNode) throw new ExchangeNotAvailable([this.id, method, url, e.type, e.message].join(' '));
throw e; // rethrow all unknown errors
}).then(response => this.handleRestErrors(response, url, method, headers, body)).then(response => this.handleRestResponse(response, url, method, headers, body));
return timeout(this.timeout, promise).catch(e => {
if (e instanceof RequestTimeout) throw new RequestTimeout(this.id + ' ' + method + ' ' + url + ' ' + e.message + ' (' + this.timeout + ' ms)');
throw e;
});
};
}
defineRestApi(api, methodName, options = {}) {
var _this = this;
for (const type of (0, _keys2.default)(api)) {
for (const httpMethod of (0, _keys2.default)(api[type])) {
let urls = api[type][httpMethod];
for (let i = 0; i < urls.length; i++) {
let url = urls[i].trim();
let splitPath = url.split(/[^a-zA-Z0-9]/);
let uppercaseMethod = httpMethod.toUpperCase();
let lowercaseMethod = httpMethod.toLowerCase();
let camelcaseMethod = this.capitalize(lowercaseMethod);
let camelcaseSuffix = splitPath.map(this.capitalize).join('');
let underscoreSuffix = splitPath.map(x => x.trim().toLowerCase()).filter(x => x.length > 0).join('_');
if (camelcaseSuffix.indexOf(camelcaseMethod) === 0) camelcaseSuffix = camelcaseSuffix.slice(camelcaseMethod.length);
if (underscoreSuffix.indexOf(lowercaseMethod) === 0) underscoreSuffix = underscoreSuffix.slice(lowercaseMethod.length);
let camelcase = type + camelcaseMethod + this.capitalize(camelcaseSuffix);
let underscore = type + '_' + lowercaseMethod + '_' + underscoreSuffix;
if ('suffixes' in options) {
if ('camelcase' in options['suffixes']) camelcase += options['suffixes']['camelcase'];
if ('underscore' in options.suffixes) underscore += options['suffixes']['underscore'];
}
if ('underscore_suffix' in options) underscore += options.underscoreSuffix;
if ('camelcase_suffix' in options) camelcase += options.camelcaseSuffix;
let partial = (() => {
var _ref = (0, _asyncToGenerator3.default)(function* (params) {
return _this[methodName](url, type, uppercaseMethod, params || {});
});
return function partial(_x) {
return _ref.apply(this, arguments);
};
})();
this[camelcase] = partial;
this[underscore] = partial;
}
}
}
}
fetch(url, method = 'GET', headers = undefined, body = undefined) {
if (isNode && this.userAgent) {
if (typeof this.userAgent == 'string') headers = extend({ 'User-Agent': this.userAgent }, headers);else if (typeof this.userAgent == 'object' && 'User-Agent' in this.userAgent) headers = extend(this.userAgent, headers);
}
if (typeof this.proxy == 'function') {
url = this.proxy(url);
if (isNode) headers = extend({ 'Origin': '*' }, headers);
} else if (typeof this.proxy == 'string') {
if (this.proxy.length) if (isNode) headers = extend({ 'Origin': '*' }, headers);
url = this.proxy + url;
}
headers = extend(this.headers, headers);
if (this.verbose) console.log(this.id, method, url, "\nRequest:\n", headers, body);
return this.executeRestRequest(url, method, headers, body);
}
fetch2(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
var _this2 = this;
return (0, _asyncToGenerator3.default)(function* () {
if (_this2.enableRateLimit) yield _this2.throttle();
let request = _this2.sign(path, api, method, params, headers, body);
return _this2.fetch(request.url, request.method, request.headers, request.body);
})();
}
request(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
return this.fetch2(path, api, method, params, headers, body);
}
handleErrors(statusCode, statusText, url, method, headers, body) {
// override me
}
defaultErrorHandler(code, reason, url, method, headers, body) {
if (this.verbose) console.log(this.id, method, url, code, reason, body ? "\nResponse:\n" + body : '');
if (code >= 200 && code <= 300) return body;
let error = undefined;
this.last_http_response = body;
let details = body;
let match = body.match(/\<title\>([^<]+)/i);
if (match) details = match[1].trim();
if ([418, 429].includes(code)) {
error = DDoSProtection;
} else if ([404, 409, 422, 500, 501, 502, 520, 521, 522, 525].includes(code)) {
error = ExchangeNotAvailable;
} else if ([400, 403, 405, 503, 530].includes(code)) {
let ddosProtection = body.match(/cloudflare|incapsula/i);
if (ddosProtection) {
error = DDoSProtection;
} else {
error = ExchangeNotAvailable;
details += ' (possible reasons: ' + ['invalid API keys', 'bad or old nonce', 'exchange is down or offline', 'on maintenance', 'DDoS protection', 'rate-limiting'].join(', ') + ')';
}
} else if ([408, 504].includes(code)) {
error = RequestTimeout;
} else if ([401, 511].includes(code)) {
error = AuthenticationError;
} else {
error = ExchangeError;
}
throw new error([this.id, method, url, code, reason, details].join(' '));
}
handleRestErrors(response, url, method = 'GET', headers = undefined, body = undefined) {
if (typeof response == 'string') return response;
return response.text().then(text => {
const args = [response.status, response.statusText, url, method, headers, text];
this.handleErrors(...args);
return this.defaultErrorHandler(...args);
});
}
handleRestResponse(response, url, method = 'GET', headers = undefined, body = undefined) {
try {
this.last_http_response = response;
if (this.parseJsonResponse) {
this.last_json_response = typeof response == 'string' && response.length > 1 ? JSON.parse(response) : response;
return this.last_json_response;
}
return response;
} catch (e) {
let maintenance = response.match(/offline|busy|retry|wait|unavailable|maintain|maintenance|maintenancing/i);
let ddosProtection = response.match(/cloudflare|incapsula|overload/i);
if (e instanceof SyntaxError) {
let error = ExchangeNotAvailable;
let details = 'not accessible from this location at the moment';
if (maintenance) details = 'offline, on maintenance or unreachable from this location at the moment';
if (ddosProtection) error = DDoSProtection;
throw new error([this.id, method, url, details].join(' '));
}
if (this.verbose) console.log(this.id, method, url, 'error', e, "response body:\n'" + response + "'");
throw e;
}
}
setMarkets(markets, currencies = undefined) {
let values = (0, _values2.default)(markets).map(market => deepExtend({
'limits': this.limits,
'precision': this.precision
}, this.fees['trading'], market));
this.markets = deepExtend(this.markets, indexBy(values, 'symbol'));
this.marketsById = indexBy(markets, 'id');
this.markets_by_id = this.marketsById;
this.symbols = (0, _keys2.default)(this.markets).sort();
this.ids = (0, _keys2.default)(this.markets_by_id).sort();
if (currencies) {
this.currencies = deepExtend(currencies, this.currencies);
} else {
const baseCurrencies = values.filter(market => 'base' in market).map(market => ({
id: market.baseId || market.base,
code: market.base,
precision: market.precision ? market.precision.base || market.precision.amount : 8
}));
const quoteCurrencies = values.filter(market => 'quote' in market).map(market => ({
id: market.quoteId || market.quote,
code: market.quote,
precision: market.precision ? market.precision.quote || market.precision.price : 8
}));
const allCurrencies = baseCurrencies.concat(quoteCurrencies);
const groupedCurrencies = groupBy(allCurrencies, 'code');
const currencies = (0, _keys2.default)(groupedCurrencies).map(code => groupedCurrencies[code].reduce((previous, current) => previous.precision > current.precision ? previous : current, groupedCurrencies[code][0]));
const sortedCurrencies = sortBy(flatten(currencies), 'code');
this.currencies = deepExtend(indexBy(sortedCurrencies, 'code'), this.currencies);
}
return this.markets;
}
loadMarkets(reload = false) {
var _this3 = this;
return (0, _asyncToGenerator3.default)(function* () {
if (!reload && _this3.markets) {
if (!_this3.marketsById) {
return _this3.setMarkets(_this3.markets);
}
return _this3.markets;
}
const markets = yield _this3.fetchMarkets();
let currencies = undefined;
if (_this3.has.fetchCurrencies) {
currencies = yield _this3.fetchCurrencies();
}
return _this3.setMarkets(markets, currencies);
})();
}
fetchTickers(symbols = undefined, params = {}) {
throw new NotSupported(this.id + ' fetchTickers not supported yet');
}
fetchOrder(id, symbol = undefined, params = {}) {
throw new NotSupported(this.id + ' fetchOrder not supported yet');
}
fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
throw new NotSupported(this.id + ' fetchOrders not supported yet');
}
fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
throw new NotSupported(this.id + ' fetchOpenOrders not supported yet');
}
fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
throw new NotSupported(this.id + ' fetchClosedOrders not supported yet');
}
fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
throw new NotSupported(this.id + ' fetchMyTrades not supported yet');
}
fetchCurrencies() {
throw new NotSupported(this.id + ' fetchCurrencies not supported yet');
}
fetchMarkets() {
return new _promise2.default((resolve, reject) => resolve(this.markets));
}
fetchOrderStatus(id, market = undefined) {
var _this4 = this;
return (0, _asyncToGenerator3.default)(function* () {
let order = yield _this4.fetchOrder(id);
return order['status'];
})();
}
account() {
return {
'free': 0.0,
'used': 0.0,
'total': 0.0
};
}
commonCurrencyCode(currency) {
if (!this.substituteCommonCurrencyCodes) return currency;
if (currency == 'XBT') return 'BTC';
if (currency == 'BCC') return 'BCH';
if (currency == 'DRK') return 'DASH';
return currency;
}
currency(code) {
if (typeof this.currencies == 'undefined') return new ExchangeError(this.id + ' currencies not loaded');
if (typeof code === 'string' && code in this.currencies) return this.currencies[code];
throw new ExchangeError(this.id + ' does not have currency code ' + code);
}
market(symbol) {
if (typeof this.markets == 'undefined') return new ExchangeError(this.id + ' markets not loaded');
if (typeof symbol === 'string' && symbol in this.markets) return this.markets[symbol];
throw new ExchangeError(this.id + ' does not have market symbol ' + symbol);
}
marketId(symbol) {
return this.market(symbol).id || symbol;
}
marketIds(symbols) {
return symbols.map(symbol => this.marketId(symbol));
}
symbol(symbol) {
return this.market(symbol).symbol || symbol;
}
extractParams(string) {
let re = /{([a-zA-Z0-9_]+?)}/g;
let matches = [];
let match;
while (match = re.exec(string)) matches.push(match[1]);
return matches;
}
implodeParams(string, params) {
for (let property in params) string = string.replace('{' + property + '}', params[property]);
return string;
}
url(path, params = {}) {
let result = this.implodeParams(path, params);
let query = this.omit(params, this.extractParams(path));
if ((0, _keys2.default)(query).length) result += '?' + this.urlencode(query);
return result;
}
parseBidAsk(bidask, priceKey = 0, amountKey = 1) {
let price = parseFloat(bidask[priceKey]);
let amount = parseFloat(bidask[amountKey]);
return [price, amount];
}
parseBidsAsks(bidasks, priceKey = 0, amountKey = 1) {
return (0, _values2.default)(bidasks || []).map(bidask => this.parseBidAsk(bidask, priceKey, amountKey));
}
fetchL2OrderBook(symbol, params = {}) {
var _this5 = this;
return (0, _asyncToGenerator3.default)(function* () {
let orderbook = yield _this5.fetchOrderBook(symbol, params);
return extend(orderbook, {
'bids': sortBy(aggregate(orderbook.bids), 0, true),
'asks': sortBy(aggregate(orderbook.asks), 0)
});
})();
}
parseOrderBook(orderbook, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1) {
timestamp = timestamp || this.milliseconds();
return {
'bids': bidsKey in orderbook ? this.parseBidsAsks(orderbook[bidsKey], priceKey, amountKey) : [],
'asks': asksKey in orderbook ? this.parseBidsAsks(orderbook[asksKey], priceKey, amountKey) : [],
'timestamp': timestamp,
'datetime': this.iso8601(timestamp)
};
}
getCurrencyUsedOnOpenOrders(currency) {
return (0, _values2.default)(this.orders).filter(order => order['status'] == 'open').reduce((total, order) => {
let symbol = order['symbol'];
let market = this.markets[symbol];
let amount = order['remaining'];
if (currency == market['base'] && order['side'] == 'sell') {
return total + amount;
} else if (currency == market['quote'] && order['side'] == 'buy') {
return total + (order['cost'] || order['price'] * amount);
} else {
return total;
}
}, 0);
}
parseBalance(balance) {
const currencies = (0, _keys2.default)(this.omit(balance, 'info'));
currencies.forEach(currency => {
if (typeof balance[currency].used == 'undefined') {
if (this.parseBalanceFromOpenOrders && 'open_orders' in balance['info']) {
const exchangeOrdersCount = balance['info']['open_orders'];
const cachedOrdersCount = (0, _values2.default)(this.orders).filter(order => order['status'] == 'open').length;
if (cachedOrdersCount == exchangeOrdersCount) {
balance[currency].used = this.getCurrencyUsedOnOpenOrders(currency);
balance[currency].total = balance[currency].used + balance[currency].free;
}
} else {
balance[currency].used = this.getCurrencyUsedOnOpenOrders(currency);
balance[currency].total = balance[currency].used + balance[currency].free;
}
}
['free', 'used', 'total'].forEach(account => {
balance[account] = balance[account] || {};
balance[account][currency] = balance[currency][account];
});
});
return balance;
}
fetchPartialBalance(part, params = {}) {
var _this6 = this;
return (0, _asyncToGenerator3.default)(function* () {
let balance = yield _this6.fetchBalance(params);
return balance[part];
})();
}
fetchFreeBalance(params = {}) {
return this.fetchPartialBalance('free', params);
}
fetchUsedBalance(params = {}) {
return this.fetchPartialBalance('used', params);
}
fetchTotalBalance(params = {}) {
return this.fetchPartialBalance('total', params);
}
filterBySinceLimit(array, since = undefined, limit = undefined) {
if (since) array = array.filter(entry => entry.timestamp > since);
if (limit) array = array.slice(0, limit);
return array;
}
parseTrades(trades, market = undefined, since = undefined, limit = undefined) {
let result = (0, _values2.default)(trades).map(trade => this.parseTrade(trade, market));
result = sortBy(result, 'timestamp', true);
return this.filterBySinceLimit(result, since, limit);
}
parseOrders(orders, market = undefined, since = undefined, limit = undefined) {
let result = (0, _values2.default)(orders).map(order => this.parseOrder(order, market));
return this.filterBySinceLimit(result, since, limit);
}
filterOrdersBySymbol(orders, symbol = undefined) {
let grouped = this.groupBy(orders, 'symbol');
if (symbol) {
if (symbol in grouped) return grouped[symbol];
return [];
}
return orders;
}
parseOHLCV(ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
return ohlcv;
}
parseOHLCVs(ohlcvs, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
ohlcvs = (0, _values2.default)(ohlcvs);
let result = [];
for (let i = 0; i < ohlcvs.length; i++) {
if (limit && result.length >= limit) break;
let ohlcv = this.parseOHLCV(ohlcvs[i], market, timeframe, since, limit);
if (since && ohlcv[0] < since) continue;
result.push(ohlcv);
}
return result;
}
editLimitBuyOrder(id, symbol, ...args) {
return this.editLimitOrder(id, symbol, 'buy', ...args);
}
editLimitSellOrder(id, symbol, ...args) {
return this.editLimitOrder(id, symbol, 'sell', ...args);
}
editLimitOrder(id, symbol, ...args) {
return this.editOrder(id, symbol, 'limit', ...args);
}
editOrder(id, symbol, ...args) {
var _this7 = this;
return (0, _asyncToGenerator3.default)(function* () {
if (!_this7.enableRateLimit) throw new ExchangeError(_this7.id + ' editOrder() requires enableRateLimit = true');
yield _this7.cancelOrder(id, symbol);
return _this7.createOrder(symbol, ...args);
})();
}
createLimitBuyOrder(symbol, ...args) {
return this.createOrder(symbol, 'limit', 'buy', ...args);
}
createLimitSellOrder(symbol, ...args) {
return this.createOrder(symbol, 'limit', 'sell', ...args);
}
createMarketBuyOrder(symbol, amount, params = {}) {
return this.createOrder(symbol, 'market', 'buy', amount, undefined, params);
}
createMarketSellOrder(symbol, amount, params = {}) {
return this.createOrder(symbol, 'market', 'sell', amount, undefined, params);
}
costToPrecision(symbol, cost) {
return parseFloat(cost).toFixed(this.markets[symbol].precision.price);
}
priceToPrecision(symbol, price) {
return parseFloat(price).toFixed(this.markets[symbol].precision.price);
}
amountToPrecision(symbol, amount) {
return this.truncate(amount, this.markets[symbol].precision.amount);
}
amountToLots(symbol, amount) {
return this.amountToPrecision(symbol, Math.floor(amount / this.markets[symbol].lot) * this.markets[symbol].lot);
}
feeToPrecision(symbol, fee) {
return parseFloat(fee).toFixed(this.markets[symbol].precision.price);
}
calculateFee(symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) {
let market = this.markets[symbol];
let rate = market[takerOrMaker];
let cost = parseFloat(this.costToPrecision(symbol, amount * price));
return {
'type': takerOrMaker,
'currency': market['quote'],
'rate': rate,
'cost': parseFloat(this.feeToPrecision(symbol, rate * cost))
};
}
Ymd(timestamp, infix = ' ') {
let date = new Date(timestamp);
let Y = date.getUTCFullYear();
let m = date.getUTCMonth() + 1;
let d = date.getUTCDate();
m = m < 10 ? '0' + m : m;
d = d < 10 ? '0' + d : d;
return Y + '-' + m + '-' + d;
}
YmdHMS(timestamp, infix = ' ') {
let date = new Date(timestamp);
let Y = date.getUTCFullYear();
let m = date.getUTCMonth() + 1;
let d = date.getUTCDate();
let H = date.getUTCHours();
let M = date.getUTCMinutes();
let S = date.getUTCSeconds();
m = m < 10 ? '0' + m : m;
d = d < 10 ? '0' + d : d;
H = H < 10 ? '0' + H : H;
M = M < 10 ? '0' + M : M;
S = S < 10 ? '0' + S : S;
return Y + '-' + m + '-' + d + infix + H + ':' + M + ':' + S;
}
};