UNPKG

crypto-nodes

Version:

308 lines (214 loc) 7.38 kB
var moment = require('moment'); var per_second = 0; var binance_obj = { binance: require('node-binance-api'), snapshots: {}, add_snapshot: function(sym, data, syms) { this.snapshots[sym] = data; if(Object.keys(this.snapshots).length == syms.length) { //console.log('FILLED'); } else { //console.log(Object.keys(this.snapshots).length); //console.log(syms.length); } }, init_ws: function (node, symbols) { var that = this; console.log('BINANCE :: Markets ' + Object.keys(symbols).join(',')); function get_snapshot() { that.binance.websockets.depthCache(Object.keys(symbols), function(symbol, data) { if(symbols[symbol] && !that.snapshots[symbol]) { that.add_snapshot(symbol, data, Object.keys(symbols)); node.send({ payload: { 'exchange' : 'binance', fees: that.fees, sym_from: symbols[symbol][0], sym_to: symbols[symbol][1], data: { b: data.bids, a: data.asks, snapshot: true } } }); per_second++; } else { //console.log('.'); } }); } if(this.snapshot_interval) { clearInterval(this.snapshot_interval); } this.snapshot_interval = setInterval(function () { that.snapshots = {}; // get_snapshot(); }, 60000); get_snapshot(); this.binance.websockets.depth(Object.keys(symbols), (data) => { var sym_from; var sym_to; //console.log(data); //console.log(data.a.length + " " + data.b.length); if(symbols[data.s]) { node.send({ payload: { 'exchange' : 'binance', fees: this.fees, sym_from: symbols[data.s][0], sym_to: symbols[data.s][1], data: { b: data.b, a: data.a, snapshot: false } } }); per_second++; } }); }, fees: {}, interval: false, connected: false, exchange_symbols: [], configured_symbols: [], enabled_symbols: [], get_exchange_symbols: function(callback) { this.binance.exchangeInfo(function (err, data) { var out = {}; if(err) { callback(out); return; } for(x in data.symbols) { var sym = data.symbols[x]; console.log(sym.symbol + " " + sym.baseAsset + "/" + sym.quoteAsset); out[sym.symbol] = [ sym.baseAsset , sym.quoteAsset ]; } callback(out); }); }, get_enabled_symbols: function() { var out = {}; for(x in this.exchange_symbols) { var pass = false; var exc_tmp = this.exchange_symbols[x]; for(y in this.configured_symbols) { var cfg_tmp = this.configured_symbols[y].split('/'); // If its matching or inverted variant matches its enabled symbol if((exc_tmp[0] == cfg_tmp[0] && exc_tmp[1] == cfg_tmp[1]) || (exc_tmp[0] == cfg_tmp[1] && exc_tmp[1] == cfg_tmp[0]) ) { pass = true; } } if(pass) { out[x] = this.exchange_symbols[x]; } } return out; }, msg: function(node, channelName, data) { var that = this; var sym = channelName.split('_'); var sym_from = sym[0]; var sym_to = sym[1]; node.send({ payload: { exchange: 'binance', fees: that.fees, sym_from: sym_from, sym_to: sym_to, data: data } }); }, init: function(config, node, symbols, callback) { var that = this; this.configured_symbols = symbols; try { this.fees = JSON.parse(config.fees); } catch (e) {} var opts = { test: config.test ? true : false, useServerTime: true, } if(config.api_key && config.api_secret) { opts.APIKEY = config.api_key; opts.APISECRET = config.api_secret; } this.binance.options(opts); if(!this.interval) { this.interval = setInterval(function () { var color = per_second > 0 ? 'green' : 'red'; // console.log('BINANCE :: ' + per_second + ' requests per second'); //console.log('BINANCE :: LATEST ' + JSON.stringify(latest)); node.status({ fill: color,shape:'ring', text: per_second + ' requests per second' }); per_second = 0; }, 1000); } this.get_exchange_symbols(function (symbols) { that.exchange_symbols = symbols; var enabled_symbols = that.get_enabled_symbols(); console.log(enabled_symbols); that.init_ws(node, enabled_symbols); }); }, } module.exports = function(RED) { const exchange = 'binance'; function binanceConnector(config) { RED.nodes.createNode(this,config); var node = this; node.on('input', function(msg) { if(config.disabled) { // Disable UI Updates if(binance_obj.interval) { clearInterval(binance_obj.interval); } // Set node status node.status({ fill: 'red',shape:'ring', text: 'Disabled' }); // Emit flush orderbook node.send({payload: { exchange: 'binance', op: 'flush' }}); return; } if(msg.payload && msg.payload.op == 'subscribe') { binance_obj.init(config, node, msg.payload.symbols); } }); node.on('close', function() { // tidy up any async code here - shutdown connections and so on. node.status({ fill: 'red',shape:'ring', text: 'Offline' }); node.send({payload: { exchange: 'binance', op: 'flush' }}); }); } function binanceOrder(config) { RED.nodes.createNode(this,config); var node = this; node.on('input', function(msg) { //console.log('BINANCE INPUT ::'); //console.log(msg); }); } function binanceBalance(config) { RED.nodes.createNode(this,config); var node = this; node.on('input', function(msg) { //console.log('BINANCE INPUT ::'); //console.log(msg); if(msg.payload && msg.payload.op && msg.payload.op == 'get_balance') { if(msg.payload.exchange && (msg.payload.exchange == 'all' || msg.payload.exchange == exchange)) { binance.balance(function (err, data) { if(err) { node.send({ payload: { exchange: exchange, op: 'get_balance', balances: [], err: err } }); } else { node.status({fill:"green",shape:"dot", text: new moment().format('HH:mm:ss') + ' Received BALANCES' }); console.log(exchange + ' :: Received balance data'); // Lets fix the formatting and keep just what we need.. var out = {}; for(x in data) { out[x] = { balance: parseFloat(data[x].available) }; } node.send({ payload: { exchange: exchange, op: 'get_balance', balances: out } }); } }); } } }); } RED.nodes.registerType("binanceConnector", binanceConnector); RED.nodes.registerType("binanceOrder", binanceOrder); RED.nodes.registerType("binanceBalance", binanceBalance); }