UNPKG

aspernaturet

Version:

A library for cryptocurrency trading and e-commerce with support for many bitcoin/ether/altcoin exchange markets and merchant APIs

1,243 lines (1,017 loc) 2.43 MB
"use strict"; /* MIT License Copyright (c) 2017 Igor Kroitor Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; function _objectValues(obj) { var values = []; var keys = Object.keys(obj); for (var k = 0; k < keys.length; ++k) values.push(obj[keys[k]]); return values; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } (function () { //----------------------------------------------------------------------------- // dependencies var CryptoJS = require('crypto-js'), qs = require('qs'); // querystring // , ws = require ('ws') // websocket //----------------------------------------------------------------------------- // this is updated by vss.js when building var version = '1.5.110'; //----------------------------------------------------------------------------- // platform detection var isNode = typeof window === 'undefined', isCommonJS = typeof module !== 'undefined' && typeof require !== 'undefined'; //----------------------------------------------------------------------------- var CCXTError = function (_Error) { _inherits(CCXTError, _Error); function CCXTError(message) { _classCallCheck(this, CCXTError); // a workaround to make `instanceof CCXTError` work in ES5 var _this = _possibleConstructorReturn(this, (CCXTError.__proto__ || Object.getPrototypeOf(CCXTError)).call(this, message)); _this.constructor = CCXTError; _this.__proto__ = CCXTError.prototype; _this.message = message; return _this; } return CCXTError; }(Error); var ExchangeError = function (_CCXTError) { _inherits(ExchangeError, _CCXTError); function ExchangeError(message) { _classCallCheck(this, ExchangeError); var _this2 = _possibleConstructorReturn(this, (ExchangeError.__proto__ || Object.getPrototypeOf(ExchangeError)).call(this, message)); _this2.constructor = ExchangeError; _this2.__proto__ = ExchangeError.prototype; _this2.message = message; return _this2; } return ExchangeError; }(CCXTError); var NotSupported = function (_ExchangeError) { _inherits(NotSupported, _ExchangeError); function NotSupported(message) { _classCallCheck(this, NotSupported); var _this3 = _possibleConstructorReturn(this, (NotSupported.__proto__ || Object.getPrototypeOf(NotSupported)).call(this, message)); _this3.constructor = NotSupported; _this3.__proto__ = NotSupported.prototype; _this3.message = message; return _this3; } return NotSupported; }(ExchangeError); var AuthenticationError = function (_ExchangeError2) { _inherits(AuthenticationError, _ExchangeError2); function AuthenticationError(message) { _classCallCheck(this, AuthenticationError); var _this4 = _possibleConstructorReturn(this, (AuthenticationError.__proto__ || Object.getPrototypeOf(AuthenticationError)).call(this, message)); _this4.constructor = AuthenticationError; _this4.__proto__ = AuthenticationError.prototype; _this4.message = message; return _this4; } return AuthenticationError; }(ExchangeError); var InsufficientFunds = function (_ExchangeError3) { _inherits(InsufficientFunds, _ExchangeError3); function InsufficientFunds(message) { _classCallCheck(this, InsufficientFunds); var _this5 = _possibleConstructorReturn(this, (InsufficientFunds.__proto__ || Object.getPrototypeOf(InsufficientFunds)).call(this, message)); _this5.constructor = InsufficientFunds; _this5.__proto__ = InsufficientFunds.prototype; _this5.message = message; return _this5; } return InsufficientFunds; }(ExchangeError); var NetworkError = function (_CCXTError2) { _inherits(NetworkError, _CCXTError2); function NetworkError(message) { _classCallCheck(this, NetworkError); var _this6 = _possibleConstructorReturn(this, (NetworkError.__proto__ || Object.getPrototypeOf(NetworkError)).call(this, message)); _this6.constructor = NetworkError; _this6.__proto__ = NetworkError.prototype; _this6.message = message; return _this6; } return NetworkError; }(CCXTError); var DDoSProtection = function (_NetworkError) { _inherits(DDoSProtection, _NetworkError); function DDoSProtection(message) { _classCallCheck(this, DDoSProtection); var _this7 = _possibleConstructorReturn(this, (DDoSProtection.__proto__ || Object.getPrototypeOf(DDoSProtection)).call(this, message)); _this7.constructor = DDoSProtection; _this7.__proto__ = DDoSProtection.prototype; _this7.message = message; return _this7; } return DDoSProtection; }(NetworkError); var RequestTimeout = function (_NetworkError2) { _inherits(RequestTimeout, _NetworkError2); function RequestTimeout(message) { _classCallCheck(this, RequestTimeout); var _this8 = _possibleConstructorReturn(this, (RequestTimeout.__proto__ || Object.getPrototypeOf(RequestTimeout)).call(this, message)); _this8.constructor = RequestTimeout; _this8.__proto__ = RequestTimeout.prototype; _this8.message = message; return _this8; } return RequestTimeout; }(NetworkError); var ExchangeNotAvailable = function (_NetworkError3) { _inherits(ExchangeNotAvailable, _NetworkError3); function ExchangeNotAvailable(message) { _classCallCheck(this, ExchangeNotAvailable); var _this9 = _possibleConstructorReturn(this, (ExchangeNotAvailable.__proto__ || Object.getPrototypeOf(ExchangeNotAvailable)).call(this, message)); _this9.constructor = ExchangeNotAvailable; _this9.__proto__ = ExchangeNotAvailable.prototype; _this9.message = message; return _this9; } return ExchangeNotAvailable; }(NetworkError); //----------------------------------------------------------------------------- // utility helpers var sleep = function sleep(ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); }; var decimal = function decimal(float) { return parseFloat(float).toString(); }; var timeout = function timeout(ms, promise) { return Promise.race([promise, sleep(ms).then(function () { throw new RequestTimeout('request timed out'); })]); }; var capitalize = function capitalize(string) { return string.length ? string.charAt(0).toUpperCase() + string.slice(1) : string; }; var keysort = function keysort(object) { var result = {}; Object.keys(object).sort().forEach(function (key) { return result[key] = object[key]; }); return result; }; var extend = function extend() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var result = {}; var _loop = function _loop(i) { if (_typeof(args[i]) === 'object') Object.keys(args[i]).forEach(function (key) { return result[key] = args[i][key]; }); }; for (var i = 0; i < args.length; i++) { _loop(i); }return result; }; var omit = function omit(object) { var result = extend(object); for (var i = 1; i < arguments.length; i++) { if (typeof arguments[i] === 'string') delete result[arguments[i]];else if (Array.isArray(arguments[i])) for (var k = 0; k < arguments[i].length; k++) { delete result[arguments[i][k]]; } }return result; }; var indexBy = function indexBy(array, key) { var result = {}; for (var i = 0; i < array.length; i++) { var element = array[i]; if (typeof element[key] != 'undefined') { result[element[key]] = element; } } return result; }; var sortBy = function sortBy(array, key) { var descending = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; descending = descending ? -1 : 1; return array.sort(function (a, b) { return a[key] < b[key] ? -descending : a[key] > b[key] ? descending : 0; }); }; var flatten = function flatten(array) { var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; for (var i = 0, length = array.length; i < length; i++) { var value = array[i]; if (Array.isArray(value)) { flatten(value, result); } else { result.push(value); } } return result; }; var unique = function unique(array) { return array.filter(function (value, index, self) { return self.indexOf(value) == index; }); }; var pluck = function pluck(array, key) { return array.filter(function (element) { return typeof element[key] != 'undefined'; }).map(function (element) { return element[key]; }); }; var urlencode = function urlencode(object) { return qs.stringify(object); }; var sum = function sum() { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } var result = args.filter(function (arg) { return typeof arg != 'undefined'; }); return result.length > 0 ? result.reduce(function (sum, value) { return sum + value; }, 0) : undefined; }; var ordered = function ordered(x) { return x; }; // a stub to keep assoc keys in order, in JS it does nothing, it's mostly for Python //----------------------------------------------------------------------------- // a cross-platform Fetch API var nodeFetch = isNode && module.require('node-fetch') // using module.require to prevent Webpack / React Native from trying to include it , windowFetch = typeof window !== 'undefined' && window.fetch // native Fetch API (in newer browsers) , xhrFetch = function xhrFetch(url, options) { var verbose = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; return (// a quick ad-hoc polyfill (for older browsers) new Promise(function (resolve, reject) { if (verbose) console.log(url, options); var xhr = new XMLHttpRequest(); var method = options.method || 'GET'; xhr.open(method, url, true); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status == 200) resolve(xhr.responseText);else { // [403, 404, ...].indexOf (xhr.status) >= 0 throw new Error(method, url, xhr.status, xhr.responseText); } } }; if (typeof options.headers != 'undefined') for (var header in options.headers) { xhr.setRequestHeader(header, options.headers[header]); }xhr.send(options.body); }) ); }; var fetch = nodeFetch || windowFetch || xhrFetch; //----------------------------------------------------------------------------- // string ←→ binary ←→ base64 conversion routines var stringToBinary = function stringToBinary(str) { var arr = new Uint8Array(str.length); for (var i = 0; i < str.length; i++) { arr[i] = str.charCodeAt(i); } return CryptoJS.lib.WordArray.create(arr); }; var stringToBase64 = function stringToBase64(string) { return CryptoJS.enc.Latin1.parse(string).toString(CryptoJS.enc.Base64); }, utf16ToBase64 = function utf16ToBase64(string) { return CryptoJS.enc.Utf16.parse(string).toString(CryptoJS.enc.Base64); }, base64ToBinary = function base64ToBinary(string) { return CryptoJS.enc.Base64.parse(string); }, base64ToString = function base64ToString(string) { return CryptoJS.enc.Base64.parse(string).toString(CryptoJS.enc.Utf8); }, binaryToString = function binaryToString(string) { return string; }; var binaryConcat = function binaryConcat() { for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } return args.reduce(function (a, b) { return a.concat(b); }); }; // url-safe-base64 without equals signs, with + replaced by - and slashes replaced by underscores var urlencodeBase64 = function urlencodeBase64(base64string) { return base64string.replace(/[=]+$/, '').replace(/\+/g, '-').replace(/\//g, '_'); }; //----------------------------------------------------------------------------- // cryptography var hash = function hash(request) { var hash = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'md5'; var digest = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'hex'; var result = CryptoJS[hash.toUpperCase()](request); return digest == 'binary' ? result : result.toString(CryptoJS.enc[capitalize(digest)]); }; var hmac = function hmac(request, secret) { var hash = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'sha256'; var digest = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'hex'; var encoding = digest == 'binary' ? 'Latin1' : capitalize(digest); return CryptoJS['Hmac' + hash.toUpperCase()](request, secret).toString(CryptoJS.enc[capitalize(encoding)]); }; //----------------------------------------------------------------------------- // a JSON Web Token authentication method var jwt = function jwt(request, secret) { var alg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'HS256'; var hash = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'sha256'; var encodedHeader = urlencodeBase64(stringToBase64(JSON.stringify({ 'alg': alg, 'typ': 'JWT' }))), encodedData = urlencodeBase64(stringToBase64(JSON.stringify(request))), token = [encodedHeader, encodedData].join('.'), signature = urlencodeBase64(utf16ToBase64(hmac(token, secret, hash, 'utf16'))); return [token, signature].join('.'); }; //----------------------------------------------------------------------------- // const WebSocket = require('ws') // const ws = new WebSocket (this.urls['websocket']) // ws.on ('open', function open () { // console.log ('connected') // // ws.send (Date.now ()) // }) // ws.on ('close', function close () { // console.log ('disconnected') // }); // ws.on ('message', function incoming (data) { // // console.log (`Roundtrip time: ${Date.now() - data} ms`); // setTimeout (function timeout () { // ws.send (Date.now ()) // }, 500) // }) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // the base class var Exchange = function Exchange(config) { var _this15 = this; this.hash = hash; this.hmac = hmac; this.jwt = jwt; // JSON Web Token this.binaryConcat = binaryConcat; this.stringToBinary = stringToBinary; this.stringToBase64 = stringToBase64; this.base64ToBinary = base64ToBinary; this.base64ToString = base64ToString; this.binaryToString = binaryToString; this.utf16ToBase64 = utf16ToBase64; this.urlencode = urlencode; this.encodeURIComponent = encodeURIComponent; this.omit = omit; this.pluck = pluck; this.unique = unique; this.extend = extend; this.flatten = flatten; this.indexBy = indexBy; this.sortBy = sortBy; this.keysort = keysort; this.decimal = decimal; this.capitalize = capitalize; this.json = JSON.stringify; this.sum = sum; this.ordered = ordered; this.encode = function (string) { return string; }; this.decode = function (string) { return string; }; if (isNode) this.nodeVersion = process.version.match(/\d+\.\d+.\d+/)[0]; this.init = function () { this.orders = {}; this.trades = {}; if (this.api) this.defineRESTAPI(this.api, 'request'); if (this.markets) this.setMarkets(this.markets); }; this.defineRESTAPI = function (api, methodName) { var _this10 = this; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.keys(api).forEach(function (type) { Object.keys(api[type]).forEach(function (httpMethod) { var urls = api[type][httpMethod]; var _loop2 = function _loop2(i) { var url = urls[i].trim(); var splitPath = url.split(/[^a-zA-Z0-9]/); var uppercaseMethod = httpMethod.toUpperCase(); var lowercaseMethod = httpMethod.toLowerCase(); var camelcaseMethod = capitalize(lowercaseMethod); var camelcaseSuffix = splitPath.map(capitalize).join(''); var underscoreSuffix = splitPath.map(function (x) { return x.trim().toLowerCase(); }).filter(function (x) { return x.length > 0; }).join('_'); if (camelcaseSuffix.indexOf(camelcaseMethod) === 0) camelcaseSuffix = camelcaseSuffix.slice(camelcaseMethod.length); if (underscoreSuffix.indexOf(lowercaseMethod) === 0) underscoreSuffix = underscoreSuffix.slice(lowercaseMethod.length); var camelcase = type + camelcaseMethod + capitalize(camelcaseSuffix); var 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; var partial = function partial(params) { return _this10[methodName](url, type, uppercaseMethod, params); }; _this10[camelcase] = partial; _this10[underscore] = partial; }; for (var i = 0; i < urls.length; i++) { _loop2(i); } }); }); }, // this.initializeStreamingAPI = function () { // this.ws = new WebSocket (this.urls['websocket']) // ws.on ('open', function open () { // console.log ('connected') // // ws.send (Date.now ()) // }) // ws.on ('close', function close () { // console.log ('disconnected') // }) // ws.on ('message', function incoming (data) { // // console.log (`Roundtrip time: ${Date.now() - data} ms`); // setTimeout (function timeout () { // ws.send (Date.now ()) // }, 500) // }) // }, this.fetch = function (url) { var method = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'GET'; var _this11 = this; var headers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var body = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 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 (this.proxy.length) headers = extend({ 'Origin': '*' }, headers); var options = { 'method': method, 'headers': headers, 'body': body }; url = this.proxy + url; if (this.verbose) console.log(this.id, method, url, "\nRequest:\n", options); return timeout(this.timeout, fetch(url, options).catch(function (e) { if (isNode) { throw new ExchangeNotAvailable([_this11.id, method, url, e.type, e.message].join(' ')); } throw e; // rethrow all unknown errors }).then(function (response) { if (typeof response == 'string') return response; return response.text().then(function (text) { if (_this11.verbose) console.log(_this11.id, method, url, text ? "\nResponse:\n" + text : ''); if (response.status >= 200 && response.status <= 300) return text; var error = undefined; var details = text; if ([429].indexOf(response.status) >= 0) { error = DDoSProtection; } else if ([404, 409, 422, 500, 501, 502, 520, 521, 522, 525].indexOf(response.status) >= 0) { error = ExchangeNotAvailable; } else if ([400, 403, 405, 503].indexOf(response.status) >= 0) { var ddosProtection = text.match(/cloudflare|incapsula/i); if (ddosProtection) { error = DDoSProtection; } else { error = ExchangeNotAvailable; details = text + ' (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].indexOf(response.status) >= 0) { error = RequestTimeout; } else if ([401, 511].indexOf(response.status) >= 0) { error = AuthenticationError; } else { error = ExchangeError; } throw new error([_this11.id, method, url, response.status, response.statusText, details].join(' ')); }); }).then(function (response) { return _this11.handleResponse(url, method, headers, response); })); }; this.handleResponse = function (url) { var method = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'GET'; var headers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var body = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; try { if (typeof body != 'string' || body.length < 2) throw new ExchangeError([this.id, method, url, 'returned empty response'].join(' ')); return JSON.parse(body); } catch (e) { var maintenance = body.match(/offline|busy|retry|wait|unavailable|maintain|maintenance|maintenancing/i); var ddosProtection = body.match(/cloudflare|incapsula|overload/i); if (e instanceof SyntaxError) { var error = ExchangeNotAvailable; var 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'" + body + "'"); throw e; } }; this.set_markets = this.setMarkets = function (markets) { var values = _objectValues(markets); this.markets = indexBy(values, 'symbol'); this.marketsById = indexBy(markets, 'id'); this.markets_by_id = this.marketsById; this.symbols = Object.keys(this.markets).sort(); this.ids = Object.keys(this.markets_by_id).sort(); var base = this.pluck(values.filter(function (market) { return 'base' in market; }), 'base'); var quote = this.pluck(values.filter(function (market) { return 'quote' in market; }), 'quote'); this.currencies = this.unique(base.concat(quote)); return this.markets; }; this.load_markets = this.loadMarkets = function () { var _this12 = this; var reload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; if (!reload && this.markets) { if (!this.marketsById) { return new Promise(function (resolve, reject) { return resolve(_this12.setMarkets(_this12.markets)); }); } return new Promise(function (resolve, reject) { return resolve(_this12.markets); }); } return this.fetchMarkets().then(function (markets) { return _this12.setMarkets(markets); }); }; this.fetch_tickers = function () { var symbols = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; return this.fetchTickers(symbols); }; this.fetchTickers = function () { var symbols = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; throw new NotSupported(this.id + ' API does not allow to fetch all tickers at once with a single call to fetch_tickers () for now'); }; this.fetch_markets = function () { return this.fetchMarkets(); }; this.fetchMarkets = function () { var _this13 = this; return new Promise(function (resolve, reject) { return resolve(_this13.markets); }); }; this.fetchOrderStatus = function (id) { var market, order, _arguments2 = arguments; return Promise.resolve().then(function () { market = _arguments2.length > 1 && _arguments2[1] !== undefined ? _arguments2[1] : undefined; return fetchOrder(id); }).then(function (_resp) { order = _resp; return order['status']; }); }; this.account = function () { return { 'free': 0.0, 'used': 0.0, 'total': 0.0 }; }; this.commonCurrencyCode = function (currency) { if (!this.substituteCommonCurrencyCodes) return currency; if (currency == 'XBT') return 'BTC'; if (currency == 'BCC') return 'BCH'; if (currency == 'DRK') return 'DASH'; return currency; }; this.market = function (symbol) { return typeof symbol === 'string' && typeof this.markets != 'undefined' && typeof this.markets[symbol] != 'undefined' ? this.markets[symbol] : symbol; }; this.market_id = this.marketId = function (symbol) { return this.market(symbol).id || symbol; }; this.market_ids = this.marketIds = function (symbols) { var _this14 = this; return symbols.map(function (symbol) { return _this14.marketId(symbol); }); }; this.symbol = function (symbol) { return this.market(symbol).symbol || symbol; }; this.extract_params = this.extractParams = function (string) { var re = /{([a-zA-Z0-9_]+?)}/g; var matches = []; var match = void 0; while (match = re.exec(string)) { matches.push(match[1]); }return matches; }; this.implode_params = this.implodeParams = function (string, params) { for (var property in params) { string = string.replace('{' + property + '}', params[property]); }return string; }; this.url = function (path) { var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var result = this.implodeParams(path, params); var query = this.omit(params, this.extractParams(path)); if (Object.keys(query).length) result += '?' + this.urlencode(query); return result; }; this.parseTrades = function (trades) { var market = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var result = []; for (var t = 0; t < trades.length; t++) { result.push(this.parseTrade(trades[t], market)); } return result; }; this.parseOrders = function (orders) { var market = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var result = []; for (var t = 0; t < orders.length; t++) { result.push(this.parseOrder(orders[t], market)); } return result; }; this.parseOHLCV = function (ohlcv) { var market = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var timeframe = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '1m'; var since = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; var limit = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; return ohlcv; }; this.parseOHLCVs = function (ohlcvs) { var market = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var timeframe = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '1m'; var since = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; var limit = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; var result = []; for (var t = 0; t < ohlcvs.length; t++) { result.push(this.parseOHLCV(ohlcvs[t], market, timeframe, since, limit)); } return result; }; this.createLimitBuyOrder = function (market, amount, price) { var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; return this.createOrder(market, 'limit', 'buy', amount, price, params); }; this.createLimitSellOrder = function (market, amount, price) { var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; return this.createOrder(market, 'limit', 'sell', amount, price, params); }; this.createMarketBuyOrder = function (market, amount) { var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return this.createOrder(market, 'market', 'buy', amount, undefined, params); }; this.createMarketSellOrder = function (market, amount) { var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return this.createOrder(market, 'market', 'sell', amount, undefined, params); }; this.iso8601 = function (timestamp) { return new Date(timestamp).toISOString(); }; this.parse8601 = Date.parse; this.seconds = function () { return Math.floor(_this15.milliseconds() / 1000); }; this.microseconds = function () { return Math.floor(_this15.milliseconds() * 1000); }; this.milliseconds = Date.now; this.nonce = this.seconds; this.id = undefined; this.rateLimit = 2000; // milliseconds = seconds * 1000 this.timeout = 10000; // milliseconds = seconds * 1000 this.verbose = false; this.userAgent = false; this.twofa = false; // two-factor authentication this.substituteCommonCurrencyCodes = true; this.timeFrames = undefined; this.hasFetchOHLCV = false; this.yyyymmddhhmmss = function (timestamp) { var date = new Date(timestamp); var yyyy = date.getUTCFullYear(); var MM = date.getUTCMonth(); var dd = date.getUTCDay(); var hh = date.getUTCHours(); var mm = date.getUTCMinutes(); var ss = date.getUTCSeconds(); MM = MM < 10 ? '0' + MM : MM; dd = dd < 10 ? '0' + dd : dd; hh = hh < 10 ? '0' + hh : hh; mm = mm < 10 ? '0' + mm : mm; ss = ss < 10 ? '0' + ss : ss; return yyyy + '-' + MM + '-' + dd + ' ' + hh + ':' + mm + ':' + ss; }; if (isNode) this.userAgent = { 'User-Agent': 'ccxt/' + version + ' (+https://github.com/kroitor/ccxt)' + ' Node.js/' + this.nodeVersion + ' (JavaScript)' // prepended to URL, like https://proxy.com/https://exchange.com/api... };this.proxy = ''; this.hasFetchTickers = false; this.hasFetchOHLCV = false; for (var property in config) { this[property] = config[property]; }this.account = this.account; this.fetch_balance = this.fetchBalance; this.fetch_order_book = this.fetchOrderBook; this.fetch_ticker = this.fetchTicker; this.fetch_trades = this.fetchTrades; this.fetch_order = this.fetchOrder; this.fetch_order_status = this.fetchOrderStatus; 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.create_limit_buy_order = this.createLimitBuyOrder; this.create_limit_sell_order = this.createLimitBuyOrder; this.create_market_buy_order = this.createLimitBuyOrder; this.create_market_sell_order = this.createLimitBuyOrder; this.create_order = this.createOrder; this.init(); }; //============================================================================= var _1broker = { 'id': '_1broker', 'name': '1Broker', 'countries': 'US', 'rateLimit': 1500, 'version': 'v2', 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/27766021-420bd9fc-5ecb-11e7-8ed6-56d0081efed2.jpg', 'api': 'https://1broker.com/api', 'www': 'https://1broker.com', 'doc': 'https://1broker.com/?c=en/content/api-documentation' }, 'api': { 'private': { 'get': ['market/bars', 'market/categories', 'market/details', 'market/list', 'market/quotes', 'market/ticks', 'order/cancel', 'order/create', 'order/open', 'position/close', 'position/close_cancel', 'position/edit', 'position/history', 'position/open', 'position/shared/get', 'social/profile_statistics', 'social/profile_trades', 'user/bitcoin_deposit_address', 'user/details', 'user/overview', 'user/quota_status', 'user/transaction_log'] } }, fetchCategories: function fetchCategories() { var categories, _this18 = this; return Promise.resolve().then(function () { return _this18.privateGetMarketCategories(); }).then(function (_resp) { categories = _resp; return categories['response']; }); }, fetchMarkets: function fetchMarkets() { function _recursive() { if (c < categories.length) { return Promise.resolve().then(function () { category = categories[c]; return this_.privateGetMarketList({ 'category': category.toLowerCase() }); }).then(function (_resp) { markets = _resp; for (p = 0; p < markets['response'].length; p++) { market = markets['response'][p]; id = market['symbol']; symbol = undefined; base = undefined; quote = undefined; if (category == 'FOREX' || category == 'CRYPTO') { symbol = market['name']; parts = symbol.split('/'); base = parts[0]; quote = parts[1]; } else { base = id; quote = 'USD'; symbol = base + '/' + quote; } base = this_.commonCurrencyCode(base); quote = this_.commonCurrencyCode(quote); result.push({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'info': market }); } c++; return _recursive(); }); } } var this_, categories, result, c, category, markets, p, market, id, symbol, base, quote, parts, _this19 = this; return Promise.resolve().then(function () { this_ = _this19; // workaround for Babel bug (not passing `this` to _recursive() call) return _this19.fetchCategories(); }).then(function (_resp) { categories = _resp; result = []; c = 0; return _recursive(); }).then(function () { return result; }); }, fetchBalance: function fetchBalance() { var params, balance, response, result, c, currency, total, _this23 = this, _arguments8 = arguments; return Promise.resolve().then(function () { params = _arguments8.length > 0 && _arguments8[0] !== undefined ? _arguments8[0] : {}; return _this23.loadMarkets(); }).then(function () { return _this23.privateGetUserOverview(); }).then(function (_resp) { balance = _resp; response = balance['response']; result = { 'info': response }; for (c = 0; c < _this23.currencies.length; c++) { currency = _this23.currencies[c]; result[currency] = _this23.account(); } total = parseFloat(response['balance']); result['BTC']['free'] = total; result['BTC']['total'] = total; return result; }); }, fetchOrderBook: function fetchOrderBook(market) { var params, response, orderbook, timestamp, bidPrice, askPrice, bid, ask, _this24 = this, _arguments9 = arguments; return Promise.resolve().then(function () { params = _arguments9.length > 1 && _arguments9[1] !== undefined ? _arguments9[1] : {}; return _this24.loadMarkets(); }).then(function () { return _this24.privateGetMarketQuotes(_this24.extend({ 'symbols': _this24.marketId(market) }, params)); }).then(function (_resp) { response = _resp; orderbook = response['response'][0]; timestamp = _this24.parse8601(orderbook['updated']); bidPrice = parseFloat(orderbook['bid']); askPrice = parseFloat(orderbook['ask']); bid = [bidPrice, undefined]; ask = [askPrice, undefined]; return { 'timestamp': timestamp, 'datetime': _this24.iso8601(timestamp), 'bids': [bid], 'asks': [ask] }; }); }, fetchTrades: function fetchTrades(market) { var _this25 = this; throw new ExchangeError(_this25.id + ' fetchTrades () method not implemented yet'); }, fetchTicker: function fetchTicker(market) { var result, orderbook, ticker, timestamp, _this26 = this; return Promise.resolve().then(function () { return _this26.loadMarkets(); }).then(function () { return _this26.privateGetMarketBars({ 'symbol': _this26.marketId(market), 'resolution': 60, 'limit': 1 }); }).then(function (_resp) { result = _resp; return _this26.fetchOrderBook(market); }).then(function (_resp) { orderbook = _resp; ticker = result['response'][0]; timestamp = _this26.parse8601(ticker['date']); return { 'timestamp': timestamp, 'datetime': _this26.iso8601(timestamp), 'high': parseFloat(ticker['h']), 'low': parseFloat(ticker['l']), 'bid': orderbook['bids'][0][0], 'ask': orderbook['asks'][0][0], 'vwap': undefined, 'open': parseFloat(ticker['o']), 'close': parseFloat(ticker['c']), 'first': undefined, 'last': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': undefined, 'quoteVolume': undefined }; }); }, createOrder: function createOrder(market, type, side, amount) { var price, params, order, result, _this27 = this, _arguments12 = arguments; return Promise.resolve().then(function () { price = _arguments12.length > 4 && _arguments12[4] !== undefined ? _arguments12[4] : undefined; params = _arguments12.length > 5 && _arguments12[5] !== undefined ? _arguments12[5] : {}; return _this27.loadMarkets(); }).then(function () { order = { 'symbol': _this27.marketId(market), 'margin': amount, 'direction': side == 'sell' ? 'short' : 'long', 'leverage': 1, 'type': side }; if (type == 'limit') { order['price'] = price; } else { order['type'] += '_market'; }return _this27.privateGetOrderCreate(_this27.extend(order, params)); }).then(function (_resp) { result = _resp; return { 'info': result, 'id': result['response']['order_id'] }; }); }, cancelOrder: function cancelOrder(id) { var _this28 = this; return Promise.resolve().then(function () { return _this28.loadMarkets(); }).then(function () { return _this28.privatePostOrderCancel({ 'order_id': id }); }); }, request: function request(path) { var api, method, params, headers, body, url, query, response, _this29 = this, _arguments14 = arguments; return Promise.resolve().then(function () { api = _arguments14.length > 1 && _arguments14[1] !== undefined ? _arguments14[1] : 'public'; method = _arguments14.length > 2 && _arguments14[2] !== undefined ? _arguments14[2] : 'GET'; params = _arguments14.length > 3 && _arguments14[3] !== undefined ? _arguments14[3] : {}; headers = _arguments14.length > 4 && _arguments14[