consequunturatque
Version:
A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges
347 lines (330 loc) • 13.3 kB
JavaScript
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
const { ExchangeError } = require ('./base/errors');
const Precise = require ('./base/Precise');
// ---------------------------------------------------------------------------
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': {
'cancelOrder': true,
'CORS': false,
'createOrder': true,
'fetchBalance': true,
'fetchMarkets': true,
'fetchOrderBook': true,
'fetchTicker': true,
'fetchTickers': true,
'fetchTrades': true,
},
'urls': {
'referral': 'https://www.coingi.com/?r=XTPPMC',
'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': 'https://coingi.docs.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 (params = {}) {
const response = await this.wwwGet (params);
const parts = response.split ('do=currencyPairSelector-selectCurrencyPair" class="active">');
const currencyParts = parts[1].split ('<div class="currency-pair-label">');
const result = [];
for (let i = 1; i < currencyParts.length; i++) {
const currencyPart = currencyParts[i];
const idParts = currencyPart.split ('</div>');
let id = idParts[0];
id = id.replace ('/', '-');
id = id.toLowerCase ();
const [ baseId, quoteId ] = id.split ('-');
let base = baseId.toUpperCase ();
let quote = quoteId.toUpperCase ();
base = this.safeCurrencyCode (base);
quote = this.safeCurrencyCode (quote);
const symbol = base + '/' + quote;
const precision = {
'amount': 8,
'price': 8,
};
result.push ({
'id': id,
'symbol': symbol,
'base': base,
'quote': quote,
'baseId': baseId,
'quoteId': quoteId,
'info': id,
'active': true,
'precision': precision,
'limits': {
'amount': {
'min': Math.pow (10, -precision['amount']),
'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 ();
const lowercaseCurrencies = [];
const currencies = Object.keys (this.currencies);
for (let i = 0; i < currencies.length; i++) {
const currency = currencies[i];
lowercaseCurrencies.push (currency.toLowerCase ());
}
const request = {
'currencies': lowercaseCurrencies.join (','),
};
const response = await this.userPostBalance (this.extend (request, params));
const result = { 'info': response };
for (let i = 0; i < response.length; i++) {
const balance = response[i];
const currencyId = this.safeString (balance['currency'], 'name');
const code = this.safeCurrencyCode (currencyId);
const account = this.account ();
account['free'] = this.safeString (balance, 'available');
const blocked = this.safeString (balance, 'blocked');
const inOrders = this.safeString (balance, 'inOrders');
const withdrawing = this.safeString (balance, 'withdrawing');
account['used'] = Precise.stringAdd (Precise.stringAdd (blocked, inOrders), withdrawing);
result[code] = account;
}
return this.parseBalance (result, false);
}
async fetchOrderBook (symbol, limit = 512, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'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
};
const orderbook = await this.currentGetOrderBookPairAskCountBidCountDepth (this.extend (request, params));
return this.parseOrderBook (orderbook, symbol, undefined, 'bids', 'asks', 'price', 'baseAmount');
}
parseTicker (ticker, market = undefined) {
const timestamp = this.milliseconds ();
let symbol = undefined;
if (market !== undefined) {
symbol = market['symbol'];
}
return {
'symbol': symbol,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'high': this.safeNumber (ticker, 'high'),
'low': this.safeNumber (ticker, 'low'),
'bid': this.safeNumber (ticker, 'highestBid'),
'bidVolume': undefined,
'ask': this.safeNumber (ticker, 'lowestAsk'),
'askVolume': undefined,
'vwap': undefined,
'open': undefined,
'close': undefined,
'last': undefined,
'previousClose': undefined,
'change': undefined,
'percentage': undefined,
'average': undefined,
'baseVolume': this.safeNumber (ticker, 'baseVolume'),
'quoteVolume': this.safeNumber (ticker, 'counterVolume'),
'info': ticker,
};
}
async fetchTickers (symbols = undefined, params = {}) {
await this.loadMarkets ();
const response = await this.currentGet24hourRollingAggregation (params);
const result = {};
for (let t = 0; t < response.length; t++) {
const ticker = response[t];
const base = ticker['currencyPair']['base'].toUpperCase ();
const quote = ticker['currencyPair']['counter'].toUpperCase ();
const symbol = base + '/' + quote;
let market = undefined;
if (symbol in this.markets) {
market = this.markets[symbol];
}
result[symbol] = this.parseTicker (ticker, market);
}
return this.filterByArray (result, 'symbol', symbols);
}
async fetchTicker (symbol, params = {}) {
await this.loadMarkets ();
const 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) {
const priceString = this.safeString (trade, 'price');
const amountString = this.safeString (trade, 'amount');
const price = this.parseNumber (priceString);
const amount = this.parseNumber (amountString);
const cost = this.parseNumber (Precise.stringMul (priceString, amountString));
const timestamp = this.safeInteger (trade, 'timestamp');
const id = this.safeString (trade, 'id');
const marketId = this.safeString (trade, 'currencyPair');
const symbol = this.safeSymbol (marketId, market);
return {
'id': id,
'info': trade,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'symbol': symbol,
'type': undefined,
'side': undefined, // type
'order': undefined,
'takerOrMaker': undefined,
'price': price,
'amount': amount,
'cost': cost,
'fee': undefined,
};
}
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'pair': market['id'],
'maxCount': 128,
};
const response = await this.currentGetTransactionsPairMaxCount (this.extend (request, params));
return this.parseTrades (response, market, since, limit);
}
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets ();
const request = {
'currencyPair': this.marketId (symbol),
'volume': amount,
'price': price,
'orderType': (side === 'buy') ? 0 : 1,
};
const response = await this.userPostAddOrder (this.extend (request, params));
return {
'info': response,
'id': response['result'],
};
}
async cancelOrder (id, symbol = undefined, params = {}) {
await this.loadMarkets ();
const request = {
'orderId': id,
};
return await this.userPostCancelOrder (this.extend (request, params));
}
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);
}
const 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 ();
const nonce = this.nonce ();
const request = this.extend ({
'token': this.apiKey,
'nonce': nonce,
}, query);
const 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) {
const 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;
}
};