Publish Nerbus source snapshot and build documentation

This commit is contained in:
Nerbus Contributors committed 2026-10-17 18:56:29 +00:00
commit 76cccceca7
198 files changed
+338574

No files matched your search

+194
View File
@@ -0,0 +1,194 @@
const request = require('postman-request');
const base_url = 'https://dexomy.com/api/v2/';
const market_url_template = 'https://dexomy.com/exchange/dashboard?coin_pair={coin}_{base}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'get-pair-list/';
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (!body.success)
return cb((body.message != null ? body.message : api_error_msg), null, null);
else {
try {
// find the correct coin pair record
const pairObject = body.data.find(item => item.coin_pair_name === `${coin}/${exchange}`);
if (pairObject) {
const coindata = {
parent_coin_id: pairObject.parent_coin_id,
child_coin_id: pairObject.child_coin_id
};
const summary = {
'high': parseFloat(pairObject.high) || 0,
'low': parseFloat(pairObject.low) || 0,
'volume': parseFloat(pairObject.volume) || 0,
'last': parseFloat(pairObject.last_price) || 0,
'change': parseFloat(pairObject.price_change) || 0
};
return cb(null, summary, coindata);
} else
return cb(api_error_msg, null, null);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
function get_trades(parent_coin_id, child_coin_id, api_error_msg, cb) {
const req_url = `${base_url}get-exchange-market-trades?base_coin_id=${parent_coin_id}&trade_coin_id=${child_coin_id}`;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (!body.success)
return cb((body.message != null ? body.message : api_error_msg), null);
else {
try {
let trades = [];
for (let t = 0; t < body.data.transactions.data.length; t++) {
// convert the string timestamp to iso time and then to a unix timestamp
const isoTime = body.data.transactions.data[t].time.replace(' ', 'T') + 'Z';
const unixTimestamp = Math.floor(new Date(isoTime).getTime() / 1000);
trades.push({
ordertype: body.data.transactions.data[t].price_order_type.toString().toUpperCase(),
price: parseFloat(body.data.transactions.data[t].price) || 0,
quantity: parseFloat(body.data.transactions.data[t].amount) || 0,
timestamp: unixTimestamp
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(parent_coin_id, child_coin_id, api_error_msg, cb) {
const req_url = `${base_url}get-exchange-all-orders?base_coin_id=${parent_coin_id}&trade_coin_id=${child_coin_id}`;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (!body.success)
return cb((body.message != null ? body.message : api_error_msg), null, null);
else {
try {
let buys = [];
let sells = [];
for (let b = 0; b < body.data.buy_orders.data.length; b++) {
buys.push({
price: parseFloat(body.data.buy_orders.data[b].price) || 0,
quantity: parseFloat(body.data.buy_orders.data[b].amount) || 0
});
}
for (let s = 0; s < body.data.sell_orders.data.length; s++) {
sells.push({
price: parseFloat(body.data.sell_orders.data[s].price) || 0,
quantity: parseFloat(body.data.sell_orders.data[s].amount) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
});
}
function get_chartdata(parent_coin_id, child_coin_id, api_error_msg, cb) {
const end = Date.now();
const start = end - 86400000;
const req_url = `${base_url}get-exchange-chart-data?base_coin_id=${parent_coin_id}&trade_coin_id=${child_coin_id}&interval=15`;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function(error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object' || typeof body == 'string' || body instanceof String)
return cb(api_error_msg, null);
else if (!body.success)
return cb((body.message != null ? body.message : api_error_msg), null);
else {
try {
let chartdata = [];
for (let c = 0; c < body.data.length; c++) {
// only take values more recent than the last 24 hours
if ((body.data[c].time * 1000) > start)
chartdata.push([
parseInt(body.data[c].time * 1000),
parseFloat(body.data[c].open) || 0,
parseFloat(body.data[c].high) || 0,
parseFloat(body.data[c].low) || 0,
parseFloat(body.data[c].close) || 0
]);
}
return cb(null, chartdata);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
module.exports = {
market_name: 'Dexomy',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACbVBMVEUAAAAoTTU2RzdBISEnAQQjIBkpGxolDg9bMi6sTD4nDhlTGyAVTy4QDwzl5uBbNjEUSCllcnIgJR0AFRcAEhYLNyK5KSA8KCgHPCU/TkkuJCUMHhy8q6eOlpUvNDMSMx1IVE1qXVJCWk8zRTGZeGSKk2/GnIFx0ZRQgl2Nonppl3geWy9WV1aOeXusSz4iOyFcOzMxRzI6KCWFiYmIMjKhMDCHeGuMZlYgAQM3OThXISe5pIC3wbVQZU5aOzNlZFdigH9sbGegMixKBAjEYlBBDQ1ZaE0dNiynSzhXGB5EFBaMkZJhX2EcERVkMDGhb2sdExgoQCJKJh9sGxtgPz+OEhM0Py2jamYKExNiNyo2AAdABwJjKiVZWVeOTj8bXzm4Tjk3STd3Oi0mKi0KOiosJScrMSQ3KiN2JyMANiJZHB9NKhobFBWOEBRqCxRVDxMKDxN9BhMBCgpKAAUuAAKrxY6DsXpkc3aAqnOTdHN/unHcgXBla255mWtjZmFLa19SjFokhFmPlFTCWVLNcU5HTEhHRUaNYENveUKTZEIjSUKfaEGQZkC4Uz01YjtkdzokZzo9YzpXOzrpSzk7VDg3NDjJPze0SjZMPjVvODJvSDEVPjFVNTGUNjBNMjCGNy+2Ly8pPi3XMS1RKi1eSiykSytAPisfMCvZJykkQCh+NCg+OCU4RSRKMSQ6MyMeICJYMCGsHiE5FyEAKB9AJh9SJB9dQh0AOx2gLB0vLB0PJR0zHR0hHRx8GhuJEBtuDxsCFhhsHReiDxefGxYgDhROABQALhMCIBMoFxIrGRBTBg0tBg13AAumAAZhAADJFxIcAAAAXXRSTlMA/hMI1UAcD/z6+vf29PLy8vHx8fHw8O/v7e3t7Onp5uXf3tzVzMrJx8XFxcG/v7+9vby7u7m4trW0tKupqKelnpyclZCPjoyBfHp5dnNubGVXV1FORUA+PTAvJgb/bIgPAAABGklEQVQY0w3HQ2IDABAAwI1r27Zt23Zss7Zt27Zt803N3AaS1bxdbR1tHJz8fXyjsgEAU1ez1kTYO+vt3DkR89MASgpMqllfjEf+WMsgQ5AIgMLZrf5JN4nsq4Wlka4gHED+RT/l2znTkzj99IzQzIH05pWq7XdkYVFcI/OXW58CWfH2HTfGSfrosLLxn9NFFwDwu1xXQqtPsmY5PAHTAlAxlQ9UqoIiiUNmf9wtG0KCcvn+aGu4R0Bg6dvL/YQV6HlF0NvMsEhscIXkVkwOhegty+s5o+Jct9rzqY0jRB5A7JBIRBdSGgZ6hl9p1igApClvhjDf3k06lB0jMgAgBP+5yz0QSmUSWl+q/JF4VS0dbV0NAxVzd4z8/2atXThWWOQQAAAAAElFTkSuQmCC',
market_url_template: market_url_template,
market_url_case: 'u',
get_data: function(settings, cb) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats, coindata) {
if (summary_error == null) {
get_orders(coindata.parent_coin_id, coindata.child_coin_id, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(coindata.parent_coin_id, coindata.child_coin_id, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_chartdata(coindata.parent_coin_id, coindata.child_coin_id, settings.api_error_msg, function (chart_error, chartdata) {
if (chart_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: chartdata});
else
return cb(chart_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
} else
return cb(summary_error, null);
});
}
};
+183
View File
@@ -0,0 +1,183 @@
const request = require('postman-request');
const base_url = 'https://api.dex-trade.com/v1/public/';
const base_chart_url = 'https://socket.dex-trade.com/graph/';
const market_url_template = 'https://dex-trade.com/spot/trading/{coin}{base}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, bid, ask, cb) {
const req_url = base_url + 'ticker?pair=' + coin + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.status == null || body.status == false)
return cb((body.error != null ? body.error : api_error_msg), null);
else {
try {
const summary = {
'high': parseFloat(body.data.high) || 0,
'low': parseFloat(body.data.low) || 0,
'volume': parseFloat(body.data.volume_24H) || 0,
'bid': parseFloat(bid) || 0,
'ask': parseFloat(ask) || 0,
'last': parseFloat(body.data.last) || 0
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'trades?pair=' + coin + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.status == null || body.status == false)
return cb((body.error != null ? body.error : api_error_msg), null);
else {
try {
let trades = [];
for (let t = 0; t < body.data.length; t++) {
trades.push({
ordertype: body.data[t].type,
price: parseFloat(body.data[t].rate) || 0,
quantity: parseFloat(body.data[t].volume) || 0,
timestamp: parseInt(body.data[t].timestamp)
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'book?pair=' + coin + exchange;
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (body.status == null || body.status == false)
return cb((body.error != null ? body.error : api_error_msg), null, null);
else {
try {
let buys = [];
let sells = [];
for (let b = 0; b < body.data.buy.length; b++) {
buys.push({
price: parseFloat(body.data.buy[b].rate) || 0,
quantity: parseFloat(body.data.buy[b].volume) || 0
});
}
for (let s = 0; s < body.data.sell.length; s++) {
sells.push({
price: parseFloat(body.data.sell[s].rate) || 0,
quantity: parseFloat(body.data.sell[s].volume) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
function get_chartdata(coin, exchange, api_error_msg, cb) {
const end = Date.now();
const start = end - 86400000;
const req_url = base_chart_url + 'hist?t=' + coin + exchange + '&r=15&limit=100';
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object' || typeof body == 'string' || body instanceof String)
return cb(api_error_msg, null);
else {
try {
let chartdata = [];
for (let c = 0; c < body.length; c++) {
// only take values more recent than the last 24 hours
if ((body[c].time * 1000) > start)
chartdata.push([
parseInt(body[c].time * 1000),
parseFloat(body[c].open) || 0,
parseFloat(body[c].high) || 0,
parseFloat(body[c].low) || 0,
parseFloat(body[c].close) || 0
]);
}
return cb(null, chartdata);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
module.exports = {
market_name: 'Dex-Trade',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGTGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0NDYwLCAyMDIwLzA1LzEyLTE2OjA0OjE3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMiAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA2LTI2VDIxOjEwOjEwLTA2OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIyLTA2LTI2VDIxOjEwOjEwLTA2OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wNi0yNlQyMToxMDoxMC0wNjowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozNDk5ZmMyYy02YjE0LWNhNDItOWNkYS05ODI4YTQ5MTBiNWMiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpjMzIwOGQ5Yy05M2MyLTNkNDEtYTI0OC0yMjhkMjJkNjhmMmEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxYmVhYmUxYS1hY2FlLTQ1NGEtYThjMy1mMjlkMWNjOTBhZjkiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxYmVhYmUxYS1hY2FlLTQ1NGEtYThjMy1mMjlkMWNjOTBhZjkiIHN0RXZ0OndoZW49IjIwMjItMDYtMjZUMjE6MTA6MTAtMDY6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4yIChXaW5kb3dzKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MzQ5OWZjMmMtNmIxNC1jYTQyLTljZGEtOTgyOGE0OTEwYjVjIiBzdEV2dDp3aGVuPSIyMDIyLTA2LTI2VDIxOjEwOjEwLTA2OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMiAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDxyZGY6QmFnPiA8cmRmOmxpPjMyOTEwNDQzQzdFMjhCQTc2QTlCNTRFQkNFMjczMDkwPC9yZGY6bGk+IDwvcmRmOkJhZz4gPC9waG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+3wqdeQAAA4xJREFUOI1NU2tMG1QUPrzpBlRs0U4efTAcK6UMQcu2zsdiZkZndKMjCyoUSCbskel8xB9zw2abmEDiwEQIREVd3TRubqL82SYT1gkUSmlpxyhtN1oeIzCpFST8+Ly96uJNvuSec/J955x7zqVx9x2a8EzSQL+Vhqw2amn7XLVHX96oVGlsaVJlUJKaFVRv0jpe2l3WZKw7XXjlSi/dHBimEecdGhrxEN0e91Hwj2Vyu31kqK41iiWZIEpgIFz9pRsXLlzm9zDWJKxD2StVjdYRJ03PLZFleILI5wvQ/MIilejLu4jiERUvRnyiBIaqWvx3tmp34HsmdLzuFBd6QVfS4/PPkcs9RTQzt0BHjr5nJIrGWmEqFI/n4zVDDTwe7wOBu34/Fu7fx++Li6DIRCYSAUN1zae+ST/RxUtdiqSH0yEUy1hQiJOnGljZlzixu/sGNm/RYnb2Hvr6+3BvbhbllbVMIAoxAhG+MX1bSIaqg00UIeTOQ0fehWPUha/PmtDS2obo+BResiq3COabfQgEAvjhcifzrQVFJGJvacV5Ktr6vJsoEhtVGsywTMM2G/YfeIMTk1PkWJ/9JH/UvCe0aGg4A7P5N+zeW8F8Aqjzt/hJ/KhiRbJOynsMBoP4sfNnaJ8tRlyCBPKsPEgz1UhX5CKW2U3NLTh3/jscOPwWkkUZSJfn/MUSJa7WHHqH92yxWNB9vYdNIgVpshxODiNNpgJFPQS7YxST/gB27ipBZnYBHnlswwrlFWi9QqYmX78JoVAInT918fIj40ScLM/KR6pMyX11H3zIE7V/9iW3c9Sbp6miuqYlbJTuq+TBcBums+dQrNNDkCTh/QtFMjyl2YZr164/GG1axgZoirZfpK86TMrY2CQ4nE78/9jtdpQb9kO3aw+am1vhdI3B4/PC6/Xh1q3bKC2rxPETp7fR0vIyvfn2+x/LMnOhe1GPg4ePwniyHq2t7VxkaelPhhACU/+MUCiS8vJfNbxuWlldZavsnyLvZICU6qLecCAiJhmFRdv5Kh87ZkRbeweustK9vrtsmQY4OTunwOp2eykwPUvUZxmhwMw8ucYnqLTM8EnsGjFfKqK4fz+VgCGGE6MFKXhZv69jcMgWOb8QIuuwk2jI5iSbY4wGbaP0a6+Z6usbnynWlXzBlmRMqlAHMxS5wY25GvfTz+00nTB+tKPHfIP6+gfJ5ZogO+P9DaehK5oI+uoTAAAAAElFTkSuQmCC',
market_url_template: market_url_template,
market_url_case: 'u',
get_data: function(settings, cb) {
// ensure coin info is uppercase
settings.coin = settings.coin.toUpperCase();
settings.exchange = settings.exchange.toUpperCase();
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, (buys == null || buys.length == 0 ? null : buys[0].price), (sells == null || sells.length == 0 ? null : sells[0].price), function(summary_error, stats) {
if (summary_error == null) {
get_chartdata(settings.coin, settings.exchange, settings.api_error_msg, function (chart_error, chartdata) {
if (chart_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: chartdata});
else
return cb(chart_error, null);
});
} else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};
+166
View File
@@ -0,0 +1,166 @@
const request = require('postman-request');
const base_url = 'https://api.freiexchange.com/public/';
const market_url_template = '{url_prefix}/market/{coin}/{base}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'ticker/' + coin;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object') {
const summary = {
'high': 0,
'low': 0,
'volume': 0,
'volume_btc': 0,
'bid': 0,
'ask': 0,
'last': 0,
'change': 0
};
return cb(null, summary);
} else if (body.success != null && body.success == false)
return cb((body.result != null && body.result.message != null ? body.result.message : api_error_msg), null);
else {
try {
const prefix = body[coin + '_' + exchange];
const summary = {
'high': parseFloat(prefix[0].high) || 0,
'low': parseFloat(prefix[0].low) || 0,
'volume': parseFloat(prefix[0].volume24h) || 0,
'volume_btc': parseFloat(prefix[0][`volume24h_${exchange.toLowerCase()}`]) || 0,
'bid': parseFloat(prefix[0].highestBuy) || 0,
'ask': parseFloat(prefix[0].lowestSell) || 0,
'last': parseFloat(prefix[0].last) || 0,
'change': parseFloat(prefix[0].percent_change_24h) || 0
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
// NOTE: Commenting out the trade data since the trades api seems to have been discontinued.
// It will be reimplemented again later if the trades api ever returns.
// const req_url = base_url + 'trades/' + coin + (exchange == 'LTC' ? '/LTC' : '');
// // pause for 2 seconds before continuing
// rateLimit.schedule(function() {
// request({uri: req_url, json: true}, function (error, response, body) {
// if (error)
// return cb(error, null);
// else if (body == null || body == '' || typeof body !== 'object')
// return cb(api_error_msg, null);
// else if (body.success != null && body.success == false)
// return cb((body.result != null && body.result.message != null ? body.result.message : api_error_msg), null);
// else {
// try {
// let trades = [];
// for (let t = 0; t < body.length; t++) {
// trades.push({
// ordertype: body[t].type,
// price: parseFloat(body[t].price) || 0,
// quantity: parseFloat(body[t].total_coin) || 0,
// timestamp: parseInt(new Date(body[t].time.toString().replace(' ', 'T') + 'Z').getTime() / 1000)
// });
// }
// return cb(null, trades);
// } catch(err) {
// return cb(api_error_msg, null);
// }
// }
// });
// });
return cb(null, []);
}
function get_orders(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'orderbook/' + coin + (exchange == 'LTC' ? '/LTC' : '');
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (body.success != null && body.success == false)
return cb((body.result != null && body.result.message != null ? body.result.message : api_error_msg), null, null);
else {
try {
let buys = [];
let sells = [];
for (let b = 0; b < body.BUY.length; b++) {
buys.push({
price: parseFloat(body.BUY[b].price) || 0,
quantity: parseFloat(body.BUY[b].amount) || 0
});
}
for (let s = 0; s < body.SELL.length; s++) {
sells.push({
price: parseFloat(body.SELL[s].price) || 0,
quantity: parseFloat(body.SELL[s].amount) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
module.exports = {
market_name: 'FreiExchange',
market_name_alt: 'FreiXLite',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF8WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0NDYwLCAyMDIwLzA1LzEyLTE2OjA0OjE3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMiAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA2LTI2VDE2OjU2OjA2LTA2OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIyLTA2LTI2VDE2OjU2OjA2LTA2OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wNi0yNlQxNjo1NjowNi0wNjowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpjM2IyNDVkYy1kZDI2LWYwNGEtYmIwYS03OWJjNDhmZTQxMzMiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDozZWIzNDAxZC00N2U4LTFmNGUtOGYwMi1kZmMzODg0MzFlZWYiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3NzY1YTNlYi1mMjRlLWVlNGQtOGM0My0xYTY3NjgzYTNkMTAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjc3NjVhM2ViLWYyNGUtZWU0ZC04YzQzLTFhNjc2ODNhM2QxMCIgc3RFdnQ6d2hlbj0iMjAyMi0wNi0yNlQxNjo1NjowNi0wNjowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjIgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjM2IyNDVkYy1kZDI2LWYwNGEtYmIwYS03OWJjNDhmZTQxMzMiIHN0RXZ0OndoZW49IjIwMjItMDYtMjZUMTY6NTY6MDYtMDY6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4yIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz48i0LMAAAC2UlEQVQ4jV1T70tTURh+7z0/7tbcKjT7XdC3QIi0yBD6F/rQl8A+SIUlaISETSVGn6QocFaYWhARTpG0MLAvFQZFEbg+ZVAYVnO7cwuderubc2/vOS2VLjzsfe/O87zPOee5ABwABMAOwcBrGFBjikA7k7UhJm/3c+vhVc7vdjDZcIKJvfsYB9Og9XwDcbYTylXzV8AigSCTzZ+FjOelhSg9iELo3xXqvwmRvcNFWBqGALZegCkY0MPlMHKJK4zjLMEmJLhAW0icJbhUI+E159EtvKQcxE4AuQ30c5NbvYqcAsAZQnwdbMPUIromoJQ4Jj3vwfSBxhGTHUOT4YLXh/PhTsw+G0X3+RhmX77Apf5+jHu8GCNiJhzG+UgEberRNLDJMK/o6UNcDKOaFghg3nXw/8eurCRU6ToZDGJGuSD0ADzSAtNC2r+UPX8AsVBAJxrFaerVVHd8HJ2JKLqZDC6MjGCS3iXBcBp8/ub2+vrGo9XVFZDilhMvCuRTKczGZ3D+chDnzp/DdLBVT87ZNsZMU08m312N9+6fKhrMQkpYTqIosDz5adX6MsGJx3S9MPpUO1ICIYBbTX19tcVlDkzJtS0UXBezX7/gD58P0y1BXFHkkWHM5XJoVxzQt5Rk/Hejr+RSy+kzDYeqqvbDIJeP9SH6N2pJ9+MEft+0GfNUZwYG9HkU1Kg3b/En1YuUD7W+GyCiD/GwyWqQ9qeucXEwgnO073RdHbp0jTYJKetzoRBt4wnGGMMU5UJl4QLjrRQEJWHCNS56VWzT/8JDuUgUg5OkGCeK75MUKEUe5d53AF4KMAUJDEkaArqFHEJlj+I6qyKs4kwEhST1WfUfkV8J9qEUfGUAW4lcphyQAJfgFRYEubg4KWRsWU+yivCg6qeEWOri1g2hvx6LeOpDKl0T2EMCfsbgIOMlbcxzso2Jzg4mHrQzfuc6k2ePc7FrNzll+uQ8qwJ/AJ4ryGtYbOHVAAAAAElFTkSuQmCC',
market_logo_alt: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF8WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0NDYwLCAyMDIwLzA1LzEyLTE2OjA0OjE3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMiAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA2LTI2VDE5OjE0OjMzLTA2OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIyLTA2LTI2VDE5OjE0OjMzLTA2OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wNi0yNlQxOToxNDozMy0wNjowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozYjE4MmI1ZC0zZjU3LWVhNGMtYWFiYS01NmQ0YjVkZWVmNTUiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpiNWRkYTk5MS02MGNlLTc5NGQtOWFlNy04MDcwY2I3NWVjYzkiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozMjM4NjRhMi0xNjk4LWU0NGUtODA5Yy1iYjc0ZjliM2UyMmEiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjMyMzg2NGEyLTE2OTgtZTQ0ZS04MDljLWJiNzRmOWIzZTIyYSIgc3RFdnQ6d2hlbj0iMjAyMi0wNi0yNlQxOToxNDozMy0wNjowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjIgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDozYjE4MmI1ZC0zZjU3LWVhNGMtYWFiYS01NmQ0YjVkZWVmNTUiIHN0RXZ0OndoZW49IjIwMjItMDYtMjZUMTk6MTQ6MzMtMDY6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4yIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4U//lqAAACLUlEQVQ4y42TQUiTYRzGf4GXITsowi4WjIRFXnYLPNRRXSB6M8kCD2J2cAgeJJFEIwRDqA42QmjDTiW2lGkGkRRBGkSktYrUNDZnmOg+9ZvfvqfDNjEx8oWH9/I+//eB/+8hDISBD0AcWIH8GFzagDtJGNyAm+tQOQ98BwzgFTACRMiaR4AZ4DecT8FHgQ5qE8Z/wul14PX+AY+BR8Ay9B1mPKgtqJ4EhoExgHFgHq79z7hZVKSk0ymBZuDsMPAMYA6O5x7Zbrfk9WbkdivtcEgDA9pubdWVzk6F6uslUApib+DYHEACAgJZeXmyUinlTjqRkBmJSJLiNTW63NWl5xUVe4liUHm/pARMWBLI9nhkS9rt79euzyfLspSWJL9fUVBDMKjPpaUSaA2in9rbb/dGImcQmALJ55MkWZK2q6tlR6Oyk0kJ9MLr1dVAIPf7zpfu7oe5pAh2BFJzcyZBU5PMlhZJkm0YEuhBebkuDg0p0NioREGBtVpWNpE0jIW4NIUJywIpGFRa0o7LJUkyp6eVlmT39mrU49GttjZd7+nRUnGxBOlFh6Mr3NEBcbgnkGZnZS0syKqtlR0KyXI6pbo62VVVh671K1yYIoPwCYHkckmFhToKTCbE3gHvASaBH9B+FGNOb+HcHkhPslwn4MZRzAZUjWfxf0qW5zDwDdiCSvMfZTJgYgVO/QJe7u/CGDAKLAIbmftkAvwW3N2FQRP6VqFhEfKXM439a8AfCVrpWXEdq70AAAAASUVORK5CYII=',
market_url_template: market_url_template,
market_url_case: 'u',
market_url: function(settings) {
return 'https://' + (settings.exchange.toUpperCase() == 'LTC' ? 'freixlite' : 'freiexchange') + '.com';
},
isAlt: function(settings) {
return settings.exchange.toUpperCase() == 'LTC';
},
get_data: function(settings, cb) {
// ensure coin info is uppercase
settings.coin = settings.coin.toUpperCase();
settings.exchange = settings.exchange.toUpperCase();
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats) {
if (summary_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: null});
else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};
+139
View File
@@ -0,0 +1,139 @@
const request = require('postman-request');
const base_url = 'https://trade.nestex.one/api/';
const market_url_template = 'https://trade.nestex.one/spot/{coin}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'cg/tickers/' + coin + '_' + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.error != null)
return cb(body.error, null);
else {
try {
const summary = {
'high': parseFloat(body.high) || 0,
'low': parseFloat(body.low) || 0,
'volume': parseFloat(body.base_volume) || 0,
'volume_btc': parseFloat(body.target_volume) || 0,
'bid': parseFloat(body.bid) || 0,
'ask': parseFloat(body.ask) || 0,
'last': parseFloat(body.last_price) || 0
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'cg/tradebook/' + coin + '_' + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.error != null)
return cb(body.error, null);
else {
try {
let trades = [];
for (let t = 0; t < body.data.length; t++) {
trades.push({
ordertype: body.data[t].side.toString().toUpperCase(),
price: parseFloat(body.data[t].price) || 0,
quantity: parseFloat(body.data[t].quantity) || 0,
timestamp: parseInt(body.data[t].timestamp) / 1000
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(coin, exchange, api_error_msg, cb) {
const req_url = base_url + 'cg/orderbook/' + coin + '_' + exchange + '?depth=100';
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (body.error != null)
return cb(body.error, null, null);
else {
try {
let buys = [];
let sells = [];
const bids = Object.entries(body.bids);
const asks = Object.entries(body.asks);
for (let b = 0; b < bids.length; b++) {
buys.push({
price: parseFloat(bids[b][0]) || 0,
quantity: parseFloat(bids[b][1]) || 0
});
}
for (let a = 0; a < asks.length; a++) {
sells.push({
price: parseFloat(asks[a][0]) || 0,
quantity: parseFloat(asks[a][1]) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
module.exports = {
market_name: 'NestEx',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAe1BMVEUAAAD/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQX/yQVH+eRqAAAAKXRSTlMArGRHvXthTriLf3FsaFVBMhIGpZqRd1o5JBfRysiyj4RdKSDv4NiehahrJacAAACTSURBVBjTdc1XDsIwEEXRce92nN4rbf8rRApRAAnO37vzMfBHq9T2FfQs0efGFmxu3jvFIYtuSM+Q3HRUYXHHuQHHACXrhb+CQJDMul1MRQCXAdIoCHS8tXGCGosSCoSQIVg+TIUzeicAnubSs2ZjfsyR238UtRC0r0itCOw4kpSxkWYWDqHX3bUcPJwaPhV8hZ+exboH2W57FV0AAAAASUVORK5CYII=',
market_url_template: market_url_template,
market_url_case: 'u',
get_data: function(settings, cb) {
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats) {
if (summary_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: null});
else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};
+181
View File
@@ -0,0 +1,181 @@
const request = require('postman-request');
const base_url = 'https://api.nonkyc.io/api/v2';
const market_url_template = 'https://nonkyc.io/market/{coin}_{base}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const req_url = base_url + '/market/getbysymbol/' + coin + '_' + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.error != null)
return cb((body.error.message != null ? body.error.message : api_error_msg), null);
else {
try {
const summary = {
'high': parseFloat(body.highPriceNumber) || 0,
'low': parseFloat(body.lowPriceNumber) || 0,
'volume': parseFloat(body.volumeNumber) || 0,
'volume_btc': parseFloat(body.volumeUsdNumber) || 0,
'bid': parseFloat(body.bestBidNumber) || 0,
'ask': parseFloat(body.bestAskNumber) || 0,
'last': parseFloat(body.lastPriceNumber) || 0,
'prev': parseFloat(body.yesterdayPriceNumber) || 0,
'change': parseFloat(body.changePercentNumber) || 0
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
const req_url = base_url + '/historical_trades?ticker_id=' + coin + '_' + exchange + '&limit=300';
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.error != null)
return cb((body.error.message != null ? body.error.message : api_error_msg), null);
else {
try {
let trades = [];
for (let t = 0; t < body.length; t++) {
trades.push({
ordertype: body[t].type,
price: parseFloat(body[t].price) || 0,
quantity: parseFloat(body[t].base_volume) || 0,
timestamp: parseInt(new Date(body[t].trade_timestamp).getTime() / 1000)
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(coin, exchange, api_error_msg, cb) {
const req_url = base_url + '/market/getorderbookbysymbol/' + coin + '_' + exchange;
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (body.error != null)
return cb((body.error.message != null ? body.error.message : api_error_msg), null, null);
else {
try {
let buys = [];
let sells = [];
for (let b = 0; b < body.bids.length; b++) {
buys.push({
price: parseFloat(body.bids[b].numberprice) || 0,
quantity: parseFloat(body.bids[b].quantity) || 0
});
}
for (let s = 0; s < body.asks.length; s++) {
sells.push({
price: parseFloat(body.asks[s].numberprice) || 0,
quantity: parseFloat(body.asks[s].quantity) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
function get_chartdata(coin, exchange, api_error_msg, cb) {
const end = Date.now() / 1000;
const start = end - 86400;
const req_url = base_url + '/market/candles/?symbol=' + coin + '_' + exchange + '&from=' + parseInt(start).toString() + '&to=' + parseInt(end).toString() + '&resolution=15' ;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object' || typeof body == 'string' || body instanceof String)
return cb(api_error_msg, null);
else if (body.error != null)
return cb((body.error.message != null ? body.error.message : api_error_msg), null);
else {
try {
let chartdata = [];
for (let c = 0; c < body.bars.length; c++) {
chartdata.push([
parseInt(body.bars[c].time),
parseFloat(body.bars[c].open) || 0,
parseFloat(body.bars[c].high) || 0,
parseFloat(body.bars[c].low) || 0,
parseFloat(body.bars[c].close) || 0
]);
}
return cb(null, chartdata);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
module.exports = {
market_name: 'Nonkyc',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKrmlDQ1BJQ0MgUHJvZmlsZQAASImVlwdUE1kXgN/MpBdaQihSQm/SWwApIbTQpYONkAQIJcZAQLEjiyu4FlREUFF0VUTBtQBiRxTbotiwb5BFRFkXC6Ki8g9wCLv7n///z3/Peed+c+e+e+97M2/OHQCoKjyJJAtWASBbnCuNCvRlJiQmMfF9AAFaAABdQOTxcyTsyMhQ9ApM6r/Lx/sAGtN3rMdi/fv9/yqqAmEOHwAoEuUUQQ4/G+Xj6HjFl0hzAUB2oXaj/FzJGLehTJeiBaL8YIzTJnhgjFPGGQPGfWKiOCjTASBQeDxpGgAUJmpn5vHT0DgUH5TtxAKRGGUJyl7Z2fMFKB9B2Rz1QW2UsfislL/ESftbzBRFTB4vTcETaxkXgp8oR5LFW/R/bsf/luws2WQOU3RQ0qVBUWP50D17kDk/RMHilPCISRYJJmoa43RZUOwk83M4SZMs4PmFKOZmhYdOcqoogKuIk8uNmWRhjn/0JEvnRylypUo57EnmScfzklCWyzJjFfZ0IVcRvyA9Jn6S80Rx4ZOckxkdMuXDUdilsihF/UJxoO9U3gDF2rNz/rJeEVcxNzc9Jkixdt5U/UIxeypmToKiNoHQz3/KJ1bhL8n1VeSSZEUq/IVZgQp7Tl60Ym4u+kJOzY1U7GEGLzhykoEIhAEe4DOVJwmAXOHC3LGFcOZLFklFaem5TDZ6woRMrphvM53pYOfgCMDYeZ14Hd4zxs8hxLg2ZVu1EwDP46Ojo6embCEtABwrRR9L15TNbCkAShcAuFLFl0nzJmzjZwmLPj1lQEe/BnrACJgDa+AAXIAH8AH+IBhEgBiQCOaitaaDbCAF+WAJWAmKQSnYALaASlAN9oAD4DA4CprAaXABXAbXwS1wDzwGctALXoNB8BGMQBCEh6gQDdKC9CETyApygFiQF+QPhUJRUCKUDKVBYkgGLYFWQaVQGVQJ7YZqoV+gk9AF6CrUCT2EuqF+6B30BUZgCkyHdWFT2BZmwWw4BI6B58Bp8AK4AC6C18EVcA18CG6EL8DX4XuwHH4NDyEAISMMxACxRlgIB4lAkpBURIosQ0qQcqQGqUdakHbkDiJHBpDPGByGhmFirDEemCBMLIaPWYBZhlmLqcQcwDRi2jB3MN2YQcx3LBWrg7XCumO52ARsGjYfW4wtx+7DnsBewt7D9mI/4nA4Bs4M54oLwiXiMnCLcWtxO3ANuPO4TlwPbgiPx2vhrfCe+Ag8D5+LL8Zvwx/Cn8PfxvfiPxHIBH2CAyGAkEQQEwoJ5YSDhLOE24Q+wghRhWhCdCdGEAXERcT1xL3EFuJNYi9xhKRKMiN5kmJIGaSVpApSPekS6QnpPZlMNiS7kWeSReQV5AryEfIVcjf5M0WNYknhUGZTZJR1lP2U85SHlPdUKtWU6kNNouZS11FrqRepz6iflGhKNkpcJYHScqUqpUal20pvlInKJsps5bnKBcrlyseUbyoPqBBVTFU4KjyVZSpVKidVulSGVGmq9qoRqtmqa1UPql5VfamGVzNV81cTqBWp7VG7qNZDQ2hGNA6NT1tF20u7ROul4+hmdC49g15KP0zvoA+qq6k7qcepL1SvUj+jLmcgDFMGl5HFWM84yrjP+KKhq8HWEGqs0ajXuK0xrDlN00dTqFmi2aB5T/OLFlPLXytTa6NWk9ZTbYy2pfZM7XztndqXtAem0ad5TONPK5l2dNojHVjHUidKZ7HOHp0bOkO6erqBuhLdbboXdQf0GHo+ehl6m/XO6vXr0/S99EX6m/XP6b9iqjPZzCxmBbONOWigYxBkIDPYbdBhMGJoZhhrWGjYYPjUiGTEMko12mzUajRorG8cZrzEuM74kQnRhGWSbrLVpN1k2NTMNN50tWmT6UszTTOuWYFZndkTc6q5t/kC8xrzuxY4C5ZFpsUOi1uWsKWzZbplleVNK9jKxUpktcOqczp2utt08fSa6V3WFGu2dZ51nXW3DcMm1KbQpsnmja2xbZLtRtt22+92znZZdnvtHtur2QfbF9q32L9zsHTgO1Q53HWkOgY4LndsdnzrZOUkdNrp9MCZ5hzmvNq51fmbi6uL1KXepd/V2DXZdbtrF4vOimStZV1xw7r5ui13O+322d3FPdf9qPufHtYemR4HPV7OMJshnLF3Ro+noSfPc7en3Ivpley1y0vubeDN867xfu5j5CPw2efTx7ZgZ7APsd/42vlKfU/4DnPcOUs55/0Qv0C/Er8OfzX/WP9K/2cBhgFpAXUBg4HOgYsDzwdhg0KCNgZ1cXW5fG4tdzDYNXhpcFsIJSQ6pDLkeahlqDS0JQwOCw7bFPYk3CRcHN4UASK4EZsinkaaRS6IPDUTNzNyZtXMF1H2UUui2qNp0fOiD0Z/jPGNWR/zONY8VhbbGqccNzuuNm443i++LF6eYJuwNOF6onaiKLE5CZ8Ul7QvaWiW/6wts3pnO88unn1/jtmchXOuztWemzX3zDzlebx5x5KxyfHJB5O/8iJ4NbyhFG7K9pRBPoe/lf9a4CPYLOgXegrLhH2pnqllqS/TPNM2pfWne6eXpw+IOKJK0duMoIzqjOHMiMz9maNZ8VkN2YTs5OyTYjVxprhtvt78hfM7JVaSYol8gfuCLQsGpSHSfTlQzpyc5lw62hjdkJnLfpB153nlVeV9yo/LP7ZQdaF44Y1FlovWLOorCCj4eTFmMX9x6xKDJSuXdC9lL929DFqWsqx1udHyouW9KwJXHFhJWpm58tdCu8Kywg+r4le1FOkWrSjq+SHwh7pipWJpcddqj9XVP2J+FP3YscZxzbY130sEJddK7UrLS7+u5a+99pP9TxU/ja5LXdex3mX9zg24DeIN9zd6bzxQplpWUNazKWxT42bm5pLNH7bM23K13Km8eitpq2yrvCK0onmb8bYN275Wplfeq/Ktatius33N9uEdgh23d/rsrK/WrS6t/rJLtOvB7sDdjTWmNeV7cHvy9rzYG7e3/WfWz7X7tPeV7vu2X7xffiDqQFuta23tQZ2D6+vgOlld/6HZh24d9jvcXG9dv7uB0VB6BByRHXn1S/Iv94+GHG09xjpWf9zk+PYTtBMljVDjosbBpvQmeXNic+fJ4JOtLR4tJ07ZnNp/2uB01Rn1M+vPks4WnR09V3Bu6Lzk/MCFtAs9rfNaH19MuHi3bWZbx6WQS1cuB1y+2M5uP3fF88rpq+5XT15jXWu67nK98YbzjRO/Ov96osOlo/Gm683mW263WjpndJ697X37wh2/O5fvcu9evxd+r/N+7P0HXbO75A8ED14+zHr49lHeo5HHK55gn5Q8VXla/kznWc1vFr81yF3kZ7r9um88j37+uIff8/r3nN+/9ha9oL4o79Pvq33p8PJ0f0D/rVezXvW+lrweGSj+Q/WP7W/M3xz/0+fPG4MJg71vpW9H3619r/V+/wenD61DkUPPPmZ/HBku+aT16cBn1uf2L/Ff+kbyv+K/Vnyz+NbyPeT7k9Hs0VEJT8obbwUQdMCpqQC82w8ANREA2i20f5g10U+PCzTxDzBO4D/xRM89Li4A1KNqrC3inAfgCDpMfdDYqB5riWJ8AOzoqBiTve94nz4mOPSPpR6vnF9L7myxXQH+IRM9/F/q/qcGY1GdwD/1vwDFOAe+Dmu0xAAAAJZlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAACQAAAAAQAAAJAAAAABAAOShgAHAAAAEgAAAISgAgAEAAAAAQAAABCgAwAEAAAAAQAAABAAAAAAQVNDSUkAAABTY3JlZW5zaG90JdHC9QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAtdpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjE5ODwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlVzZXJDb21tZW50PlNjcmVlbnNob3Q8L2V4aWY6VXNlckNvbW1lbnQ+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4xOTg8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjE0NDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cjo54jUAAAIhSURBVDgRjVPPaxNBFJ6Zna2JiJBAEHuoWKht3YBI24s Line truncated
market_url_template: market_url_template,
market_url_case: 'u',
get_data: function(settings, cb) {
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats) {
if (summary_error == null) {
get_chartdata(settings.coin, settings.exchange, settings.api_error_msg, function (chart_error, chartdata) {
if (chart_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: chartdata});
else
return cb(chart_error, null);
});
} else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};
+182
View File
@@ -0,0 +1,182 @@
const request = require('postman-request');
const base_url = 'https://api.poloniex.com/markets/';
const market_url_template = 'https://poloniex.com/trade/{coin}_{base}?type=spot';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const req_url = base_url + coin + '_' + exchange + '/ticker24h';
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.message != null)
return cb(body.message, null);
else {
try {
const summary = {
'high': parseFloat(body.high) || 0,
'low': parseFloat(body.low) || 0,
'volume': parseFloat(body.quantity) || 0,
'volume_btc': parseFloat(body.amount) || 0,
'bid': parseFloat(body.bid) || 0,
'ask': parseFloat(body.ask) || 0,
'change': parseFloat(body.dailyChange || 0) * 100
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
const req_url = base_url + coin + '_' + exchange + '/trades';
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.message != null)
return cb(body.message, null);
else {
try {
let trades = [];
for (let t = 0; t < body.length; t++) {
trades.push({
ordertype: body[t].takerSide,
price: parseFloat(body[t].price) || 0,
quantity: parseFloat(body[t].quantity) || 0,
timestamp: parseInt(new Date(body[t].ts).getTime() / 1000)
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(coin, exchange, api_error_msg, cb) {
const req_url = base_url + coin + '_' + exchange + '/orderBook?limit=50';
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (body.message != null)
return cb(body.message, null, null);
else {
try {
let buys = [];
let sells = [];
for (let b = 0; b < body.bids.length; b += 2) {
buys.push({
price: parseFloat(body.bids[b]) || 0,
quantity: parseFloat(body.bids[b + 1]) || 0
});
}
for (let s = 0; s < body.asks.length; s += 2) {
sells.push({
price: parseFloat(body.asks[s]) || 0,
quantity: parseFloat(body.asks[s + 1]) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
function get_chartdata(coin, exchange, api_error_msg, cb) {
const end = Date.now();
const start = end - 86400000;
const req_url = base_url + coin + '_' + exchange + '/candles?interval=MINUTE_15&limit=96&startTime=' + start.toString() + '&endTime=' + end.toString();
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object' || typeof body == 'string' || body instanceof String)
return cb(api_error_msg, null);
else if (body.message != null)
return cb(body.message, null);
else {
try {
let chartdata = [];
for (let c = 0; c < body.length; c++)
chartdata.push([
parseInt(body[c][9]),
parseFloat(body[c][2]) || 0,
parseFloat(body[c][1]) || 0,
parseFloat(body[c][0]) || 0,
parseFloat(body[c][3]) || 0
]);
return cb(null, chartdata);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
module.exports = {
market_name: 'Poloniex',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF8WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0NDYwLCAyMDIwLzA1LzEyLTE2OjA0OjE3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMiAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTEyLTI1VDIwOjU1OjMzLTA3OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTEyLTI1VDIwOjU1OjMzLTA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMC0xMi0yNVQyMDo1NTozMy0wNzowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDphMzU0YTQ5My02M2VlLTQ3NDUtOTAyMC1jZjQ5ZTZlODRlNDQiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDowZTZlOTkxZi05YTM4LTgxNDAtYTlmMS0yMGU3MThjOTU5YjMiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplNzcwYmQ5Zi1kMzM2LTliNGQtYmVhMC0wOTIwNjZkNDIwZDIiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmU3NzBiZDlmLWQzMzYtOWI0ZC1iZWEwLTA5MjA2NmQ0MjBkMiIgc3RFdnQ6d2hlbj0iMjAyMC0xMi0yNVQyMDo1NTozMy0wNzowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjIgKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDphMzU0YTQ5My02M2VlLTQ3NDUtOTAyMC1jZjQ5ZTZlODRlNDQiIHN0RXZ0OndoZW49IjIwMjAtMTItMjVUMjA6NTU6MzMtMDc6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4yIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4yAdy4AAACnUlEQVQ4y11TS09TQRid9raFloIY45/wHUNijEsXBjeKC40r3Wrig7b0AS229AVIotISATdiSohuVJDYEkXjxsSFCQlEDSASdvIwo4BiheOZK1x6bTLp3PnOOd/3nZlPOJKpOVs8IUWDXwqPT4p6rxTBkHSn0tKWSEqNq5J7EQgy5iGGcV+DVBw7ucIajRX33exAW6GA8PM8EoURnM/1QzQ2wZVMoZJLhBpxNpdDYmQE4Xwe7fw/QI6NXLGLGXY0hTH2eQalvzM9PbAEgrAFQ6jr7jbFxme+oCocgeIKF8uzU2B/uhW/VlYM0PzCAjR/AO5IM1alNM5//1zFoXQbLKzQmUxJobEXVSr7w6X+flOm7KvX2Hndg8WlJePs8sAAsV5UkWNV3pWxDJoFZ0tcD7wZHzeJnLvTiaPxhL4fm5qElYlcxNJAKK5wbApUsAUX+zrIwOL3H4bAV5Zf4fHB+/ARau9264a6iVUcx5YAFwSzVDMgvD5cuN9nquLdh48QV67CwgS2VHqLbBawlAhc7HtgEng7MQGNAlokAjsF7PH/BOz8cLe2wklnD7e149vyskH+ND+Psmv1SAwOoa73HkQgpLegbQnoJipDoi3QmH1scsqU/TiFT9y6re8nZ2dRRkx5LLZtInuXbnWNvC7/00ETOfD4CXaTgLU148w/NKRfeTVbsahrZDnSzgdzKtMFrK8bwPdT0xStRzkf2cRMySvd2MDpbBds5FSoGXFFY3IPK0BJ33/4ImtS9ISuq1WTTqO4srotQuxechRXWCPNxWOZLDpGRxEaHkacg3Kyp5dzEEI5y3TSMAvnoZZnsXwBgWfDaH/xEkc6M9CabxQFQXMi1vJvTL2b49zYJFV52uY466XyTB9nhVFYZlfcv+GHou2DaH9cAAAAAElFTkSuQmCC',
market_url_template: market_url_template,
market_url_case: 'u',
get_data: function(settings, cb) {
// ensure coin info is uppercase
settings.coin = settings.coin.toUpperCase();
settings.exchange = settings.exchange.toUpperCase();
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats) {
if (summary_error == null) {
get_chartdata(settings.coin, settings.exchange, settings.api_error_msg, function (chart_error, chartdata) {
if (chart_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: chartdata});
else
return cb(chart_error, null);
});
} else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};
+144
View File
@@ -0,0 +1,144 @@
const request = require('postman-request');
const base_url = 'https://qutrade.io/api/v1/';
const market_url_template = 'https://qutrade.io/en/?market={coin}_{base}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const pair_key = coin.toLowerCase() + '_' + exchange.toLowerCase();
const req_url = base_url + 'market_data/?pair=' + pair_key;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object' || body.result == null || body.list == null || body.list[pair_key] == null)
return cb(api_error_msg, null);
else if (body.result !== 'success')
return cb(body.info || api_error_msg, null);
else {
try {
const pair_data = body.list[pair_key];
const summary = {
'high': parseFloat(pair_data.high) || 0,
'low': parseFloat(pair_data.low) || 0,
'volume': parseFloat(pair_data.asset_1_volume) || 0,
'volume_btc': parseFloat(pair_data.asset_2_volume) || 0,
'bid': parseFloat(pair_data.bid) || 0,
'ask': parseFloat(pair_data.ask) || 0,
'last': parseFloat(pair_data.price) || 0,
'change': parseFloat(pair_data.trend) || 0
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
const pair_key = coin.toLowerCase() + '_' + exchange.toLowerCase();
const req_url = base_url + 'market_trades/?pair=' + pair_key + '&limit=100';
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object' || body.result == null || body.list == null || body.list.length == 0)
return cb(api_error_msg, null);
else if (body.result !== 'success')
return cb(body.info || api_error_msg, null);
else {
try {
let trades = [];
for (let t = 0; t < body.list.length; t++) {
trades.push({
ordertype: body.list[t].side.toString().toUpperCase(),
price: parseFloat(body.list[t].price) || 0,
quantity: parseFloat(body.list[t].amount) || 0,
timestamp: parseInt(body.list[t].timestamp)
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(coin, exchange, api_error_msg, cb) {
const pair_key = coin.toLowerCase() + '_' + exchange.toLowerCase();
const req_url = base_url + 'market_depth/?pair=' + pair_key + '&limit=100';
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object' || body.result == null || body.list == null || body.list[pair_key] == null)
return cb(api_error_msg, null, null);
else if (body.result !== 'success')
return cb(body.info || api_error_msg, null, null);
else {
try {
let buys = [];
let sells = [];
const pair_data = body.list[pair_key];
for (let b = 0; b < pair_data.bids.length; b++) {
buys.push({
price: parseFloat(pair_data.bids[b][0]) || 0,
quantity: parseFloat(pair_data.bids[b][1]) || 0
});
}
for (let s = 0; s < pair_data.asks.length; s++) {
sells.push({
price: parseFloat(pair_data.asks[s][0]) || 0,
quantity: parseFloat(pair_data.asks[s][1]) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
module.exports = {
market_name: 'Qutrade',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAhFBMVEUAAAAuSVwvR14vSFwwSF0wSF0wSF0wSF4xR14wR10wSF0vSF0uQ14xR1swSV0vSF0wSF0vSF0vRV4wR10vSF0vSF0xSVsvSV0wSlwxSF0wR1wuSFwwSF0vSV0wSl0vSF4uSFcyRmQuSVg6R2UsRGAxSFwwR1wySlswSF0xSlsyR18uR1sSei0+AAAAKHRSTlMAUg3n3KqdSC+jl0xCHgX89/LPvrOSiYR9d2VbWDwrJhfr2o1rUBQITdwwpgAAAJxJREFUGNNtj0kOgzAUQ02ANMxzmSmdHXr/+zWgZte3sfT99CVj59LkZNG8YDnT9X2X7HHQLW+151p9QhNOwdiadw7ASEaweEzhUCbAaQaWEREnBBTAvOUCLgGGqGh63lyv3ByAtTGQ6ivWbf8tKDHoGA9lLNMnISMIXcLikE+g1509nJhNJgLW4lgE1aa/KfSk9NjCkvgkM1/hH1/r4gv6hEKdhQAAAABJRU5ErkJggg==',
market_url_template: market_url_template,
market_url_case: 'l',
get_data: function(settings, cb) {
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats) {
if (summary_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: null});
else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};
+143
View File
@@ -0,0 +1,143 @@
const request = require('postman-request');
const base_url = 'https://yobit.net/api/3';
const market_url_template = 'https://yobit.net/en/trade/{coin}/{base}';
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
const rateLimitLib = require('../ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
function get_summary(coin, exchange, api_error_msg, cb) {
const req_url = base_url + '/ticker/' + coin + '_' + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.success == 0)
return cb((body.error != null ? body.error : api_error_msg), null);
else {
try {
const prefix = body[coin + '_' + exchange];
const summary = {
'high': parseFloat(prefix.high) || 0,
'low': parseFloat(prefix.low) || 0,
'volume': parseFloat(prefix.vol) || 0,
'bid': parseFloat(prefix.buy) || 0,
'ask': parseFloat(prefix.sell) || 0,
'last': parseFloat(prefix.last) || 0
};
return cb(null, summary);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_trades(coin, exchange, api_error_msg, cb) {
const req_url = base_url + '/trades/' + coin + '_' + exchange;
// pause for 2 seconds before continuing
rateLimit.schedule(function() {
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null);
else if (body.success == 0)
return cb((body.error != null ? body.error : api_error_msg), null);
else {
try {
const prefix = body[coin + '_' + exchange];
let trades = [];
for (let t = 0; t < prefix.length; t++) {
trades.push({
ordertype: (prefix[t].type.toLowerCase() == 'bid' ? 'BUY' : 'SELL'),
price: parseFloat(prefix[t].price) || 0,
quantity: parseFloat(prefix[t].amount) || 0,
timestamp: parseInt(prefix[t].timestamp)
});
}
return cb(null, trades);
} catch(err) {
return cb(api_error_msg, null);
}
}
});
});
}
function get_orders(coin, exchange, api_error_msg, cb) {
const req_url = base_url + '/depth/' + coin + '_' + exchange;
// NOTE: no need to pause here because this is the first api call
request({uri: req_url, json: true}, function (error, response, body) {
if (error)
return cb(error, null, null);
else if (body == null || body == '' || typeof body !== 'object')
return cb(api_error_msg, null, null);
else if (body.success == 0)
return cb((body.error != null ? body.error : api_error_msg), null, null);
else {
try {
const prefix = body[coin + '_' + exchange];
let buys = [];
let sells = [];
for (let b = 0; b < prefix.bids.length; b++) {
buys.push({
price: parseFloat(prefix.bids[b][0]) || 0,
quantity: parseFloat(prefix.bids[b][1]) || 0
});
}
for (let s = 0; s < prefix.asks.length; s++) {
sells.push({
price: parseFloat(prefix.asks[s][0]) || 0,
quantity: parseFloat(prefix.asks[s][1]) || 0
});
}
return cb(null, buys, sells);
} catch(err) {
return cb(api_error_msg, null, null);
}
}
});
}
module.exports = {
market_name: 'Yobit',
market_logo: 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAEsUExURQCZ2ACV1gCY2ACO1ACR1QCT1gCP1AKa2AGZ2AOa2QCX1wOa2AGa2ACS1QCU1gCV1wSb2QCY1wGV16Pc8tLu+Q6c2QCa2ASa2Ruk3DKt4AKZ2Aud2nrL61y/5gGS1QOb2WLB6Cyr3wOW1wSZ2GrE6XrK6zKu4EC04lG65eH1+1C75bjk9Syq3s7t+HjK64DN7ACQ1eT2/AOY2Lnk9Fq+55PV70y45Kne8hCd2sXq98vs+IXN7IrQ7YvR7gOR1ZnX8ASa2FG35Aec2WDB5wmd2tXw+QCM0zuu4Aab2QOO1AKS1ZXW70a24wGX153Z8ard8giY2Aub2QWb2bvm9cTp9mbC6GXC6MPo9h6j3Cap3iKo3iGo3s3s+Cus34nR7d3z+n3M7ACQ1Nry+tjy+pKA2eoAAADASURBVBjTY2AgDLjZgQQnkObkFuAAMsX4+HkYGHiZ2Fl5WVmYgAL8MuqsnIJxUSxmwuZ6yoI8DKwahqLMCcGeoa6O7sLaSlIM8sx+3hHxogFJkcyMbFZavAwcRoEhyT7MsTEcnE52tjZsDAwCBmHhib7RIkwOLmym+kABTjkTf68gIUtnNzYLTTU+oACLgjGLh5COiL21rior0FEcXBKSXBw8jNKyKoogPhBwMQIJdiYWFkYIn4EDTHNwirMzEAMA6McVLdcDhkkAAAAASUVORK5CYII=',
market_url_template: market_url_template,
market_url_case: 'u',
get_data: function(settings, cb) {
// ensure coin info is lowercase
settings.coin = settings.coin.toLowerCase();
settings.exchange = settings.exchange.toLowerCase();
get_orders(settings.coin, settings.exchange, settings.api_error_msg, function(order_error, buys, sells) {
if (order_error == null) {
get_trades(settings.coin, settings.exchange, settings.api_error_msg, function(trade_error, trades) {
if (trade_error == null) {
get_summary(settings.coin, settings.exchange, settings.api_error_msg, function(summary_error, stats) {
if (summary_error == null)
return cb(null, {buys: buys, sells: sells, trades: trades, stats: stats, chartdata: null});
else
return cb(summary_error, null);
});
} else
return cb(trade_error, null);
});
} else
return cb(order_error, null);
});
}
};