UNPKG

@jmparsons/ccxt

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 100+ exchanges

321 lines (304 loc) 11.7 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError } = require ('./base/errors'); // --------------------------------------------------------------------------- module.exports = class coingi extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'coingi', 'name': 'Coingi', 'rateLimit': 1000, 'countries': [ 'PA', 'BG', 'CN', 'US' ], // Panama, Bulgaria, China, US 'has': { 'CORS': false, 'fetchTickers': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/28619707-5c9232a8-7212-11e7-86d6-98fe5d15cc6e.jpg', 'api': { 'www': 'https://coingi.com', 'current': 'https://api.coingi.com', 'user': 'https://api.coingi.com', }, 'www': 'https://coingi.com', 'doc': 'http://docs.coingi.apiary.io/', }, 'api': { 'www': { 'get': [ '', ], }, 'current': { 'get': [ 'order-book/{pair}/{askCount}/{bidCount}/{depth}', 'transactions/{pair}/{maxCount}', '24hour-rolling-aggregation', ], }, 'user': { 'post': [ 'balance', 'add-order', 'cancel-order', 'orders', 'transactions', 'create-crypto-withdrawal', ], }, }, 'fees': { 'trading': { 'tierBased': false, 'percentage': true, 'taker': 0.2 / 100, 'maker': 0.2 / 100, }, 'funding': { 'tierBased': false, 'percentage': false, 'withdraw': { 'BTC': 0.001, 'LTC': 0.01, 'DOGE': 2, 'PPC': 0.02, 'VTC': 0.2, 'NMC': 2, 'DASH': 0.002, 'USD': 10, 'EUR': 10, }, 'deposit': { 'BTC': 0, 'LTC': 0, 'DOGE': 0, 'PPC': 0, 'VTC': 0, 'NMC': 0, 'DASH': 0, 'USD': 5, 'EUR': 1, }, }, }, }); } async fetchMarkets () { let response = undefined; try { this.parseJsonResponse = false; response = await this.wwwGet (); this.parseJsonResponse = true; } catch (e) { this.parseJsonResponse = true; throw e; } let parts = response.split ('do=currencyPairSelector-selectCurrencyPair" class="active">'); let currencyParts = parts[1].split ('<div class="currency-pair-label">'); let result = []; for (let i = 1; i < currencyParts.length; i++) { let currencyPart = currencyParts[i]; let idParts = currencyPart.split ('</div>'); let id = idParts[0]; let symbol = id; id = id.replace ('/', '-'); id = id.toLowerCase (); let [ base, quote ] = symbol.split ('/'); let precision = { 'amount': 8, 'price': 8, }; let lot = Math.pow (10, -precision['amount']); result.push ({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'info': id, 'lot': lot, 'active': true, 'precision': precision, 'limits': { 'amount': { 'min': lot, 'max': Math.pow (10, precision['amount']), }, 'price': { 'min': Math.pow (10, -precision['price']), 'max': undefined, }, 'cost': { 'min': 0, 'max': undefined, }, }, }); } return result; } async fetchBalance (params = {}) { await this.loadMarkets (); let lowercaseCurrencies = []; let currencies = Object.keys (this.currencies); for (let i = 0; i < currencies.length; i++) { let currency = currencies[i]; lowercaseCurrencies.push (currency.toLowerCase ()); } let balances = await this.userPostBalance ({ 'currencies': lowercaseCurrencies.join (','), }); let result = { 'info': balances }; for (let b = 0; b < balances.length; b++) { let balance = balances[b]; let currency = balance['currency']['name']; currency = currency.toUpperCase (); let account = { 'free': balance['available'], 'used': balance['blocked'] + balance['inOrders'] + balance['withdrawing'], 'total': 0.0, }; account['total'] = this.sum (account['free'], account['used']); result[currency] = account; } return this.parseBalance (result); } async fetchOrderBook (symbol, limit = 512, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let orderbook = await this.currentGetOrderBookPairAskCountBidCountDepth (this.extend ({ 'pair': market['id'], 'depth': 32, // maximum number of depth range steps 1-32 'askCount': limit, // maximum returned number of asks 1-512 'bidCount': limit, // maximum returned number of bids 1-512 }, params)); return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'baseAmount'); } parseTicker (ticker, market = undefined) { let timestamp = this.milliseconds (); let symbol = undefined; if (market) symbol = market['symbol']; return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': ticker['high'], 'low': ticker['low'], 'bid': ticker['highestBid'], 'bidVolume': undefined, 'ask': ticker['lowestAsk'], 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': undefined, 'last': undefined, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': ticker['baseVolume'], 'quoteVolume': ticker['counterVolume'], 'info': ticker, }; } async fetchTickers (symbols = undefined, params = {}) { await this.loadMarkets (); let response = await this.currentGet24hourRollingAggregation (params); let result = {}; for (let t = 0; t < response.length; t++) { let ticker = response[t]; let base = ticker['currencyPair']['base'].toUpperCase (); let quote = ticker['currencyPair']['counter'].toUpperCase (); let symbol = base + '/' + quote; let market = undefined; if (symbol in this.markets) { market = this.markets[symbol]; } result[symbol] = this.parseTicker (ticker, market); } return result; } async fetchTicker (symbol, params = {}) { await this.loadMarkets (); let tickers = await this.fetchTickers (undefined, params); if (symbol in tickers) return tickers[symbol]; throw new ExchangeError (this.id + ' return did not contain ' + symbol); } parseTrade (trade, market = undefined) { if (!market) market = this.markets_by_id[trade['currencyPair']]; return { 'id': trade['id'], 'info': trade, 'timestamp': trade['timestamp'], 'datetime': this.iso8601 (trade['timestamp']), 'symbol': market['symbol'], 'type': undefined, 'side': undefined, // type 'price': trade['price'], 'amount': trade['amount'], }; } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let response = await this.currentGetTransactionsPairMaxCount (this.extend ({ 'pair': market['id'], 'maxCount': 128, }, params)); return this.parseTrades (response, market, since, limit); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { await this.loadMarkets (); let order = { 'currencyPair': this.marketId (symbol), 'volume': amount, 'price': price, 'orderType': (side === 'buy') ? 0 : 1, }; let response = await this.userPostAddOrder (this.extend (order, params)); return { 'info': response, 'id': response['result'], }; } async cancelOrder (id, symbol = undefined, params = {}) { await this.loadMarkets (); return await this.userPostCancelOrder ({ 'orderId': id }); } sign (path, api = 'current', method = 'GET', params = {}, headers = undefined, body = undefined) { let url = this.urls['api'][api]; if (api !== 'www') { url += '/' + api + '/' + this.implodeParams (path, params); } let query = this.omit (params, this.extractParams (path)); if (api === 'current') { if (Object.keys (query).length) url += '?' + this.urlencode (query); } else if (api === 'user') { this.checkRequiredCredentials (); let nonce = this.nonce (); let request = this.extend ({ 'token': this.apiKey, 'nonce': nonce, }, query); let auth = nonce.toString () + '$' + this.apiKey; request['signature'] = this.hmac (this.encode (auth), this.encode (this.secret)); body = this.json (request); headers = { 'Content-Type': 'application/json', }; } return { 'url': url, 'method': method, 'body': body, 'headers': headers }; } async request (path, api = 'current', method = 'GET', params = {}, headers = undefined, body = undefined) { let response = await this.fetch2 (path, api, method, params, headers, body); if (typeof response !== 'string') { if ('errors' in response) throw new ExchangeError (this.id + ' ' + this.json (response)); } return response; } };