Skip to content

Instantly share code, notes, and snippets.

@pinhopro
Last active October 24, 2016 16:18
Show Gist options
  • Save pinhopro/f90bc1191c5f2f7ec296f2ce28714cb3 to your computer and use it in GitHub Desktop.
Save pinhopro/f90bc1191c5f2f7ec296f2ce28714cb3 to your computer and use it in GitHub Desktop.
var os = require('os');
var util = require('util');
var Promise = require('promise');
var WebSocketClient = require('websocket').w3cwebsocket;
var macaddress = require('macaddress');
var dgram = require('dgram');
var ip = require('ip');
/**
* @param {string} api_endpoint
* @param {Object.<string,string>} opt_extra_params
* @constructor
*/
var BlinkTradeWebSocketTransport = function(api_endpoint, opt_extra_params){
var self = this;
/**
* @type {string}
* @private
*/
this.websocket_url_ = api_endpoint;
/**
* @type {WebSocket}
* @private
*/
this.ws_ = null;
/**
*
* @type {Object.<number,*>}
* @private
*/
this.handlers_ = {};
/**
* @type {number}
* @private
*/
this.last_request_id_ = null;
/**
* @type {Object.<string,string|Array.<string>>|null}
* @private
*/
this.stun_ip_ = null;
/**
* @type {number|null}
* @private
*/
this.finger_print_ = null;
/**
* @type {number|null}
* @private
*/
this.tracking_code_ = null;
// Send a STUNT request to stun servers, so we can retrieve our public ip addresses
if (dgram) {
var socket = dgram.createSocket('udp4');
var STUN_HEADER_LENGTH = 20;
var stun_request = new Buffer(STUN_HEADER_LENGTH);
var STUN_METHOD_REQUEST = 0x000;
var STUN_BINDING_CLASS = 0x0001;
var STUN_MAGIC_COOKIE = 0x2112A442;
var STUN_TID_MAX = Math.pow(2,32);
var STUN_ATTR_MAPPED_ADDRESS = 0x0001;
var STUN_ATTR_SOURCE_ADDRESS = 0x0004;
var STUN_ATTR_CHANGE_ADDRESS = 0x0005;
var STUN_ATTR_XOR_MAPPED_ADDRESS = 0x8020;
var STUN_ATTR_XOR_MAPPED_ADDRESS_ALT = 0x0020;
var stun_tx_id = (Math.random() * STUN_TID_MAX);
stun_request.writeUInt16BE(((STUN_BINDING_CLASS|STUN_METHOD_REQUEST) & 0x3fff), 0);
stun_request.writeUInt16BE(0, 2);
stun_request.writeUInt32BE(STUN_MAGIC_COOKIE, 4);
stun_request.writeUInt32BE(0, 8);
stun_request.writeUInt32BE(0, 12);
stun_request.writeUInt32BE(stun_tx_id, 16);
socket.on('message', function(msg){
var _xor = function(a, b) {
var data = [];
if (b.length > a.length) {
var tmp = a;
a = b;
b = tmp;
}
for (var i=0, len=a.length; i<len; i++) {
data.push(a[i] ^ b[i]);
}
return new Buffer(data);
};
var block = msg.readUInt8(0);
var bit1 = block & 0x80;
var bit2 = block & 0x40;
var _isStunPacket = (bit1 === 0 && bit2 === 0) ? true : false;
if (!_isStunPacket) {
return;
}
var msg_header = msg.slice(0, STUN_HEADER_LENGTH);
var msg_attrs = msg.slice(STUN_HEADER_LENGTH, msg.length );
var offset = 0;
while (offset < msg_attrs.length) {
var attr_type = msg_attrs.readUInt16BE(offset);
offset += 2;
var attr_buff_length = msg_attrs.readUInt16BE(offset);
var block_out = attr_buff_length % 4;
if (block_out > 0) {
attr_buff_length += 4 - block_out;
}
offset += 2;
var value = msg_attrs.slice(offset, offset + attr_buff_length);
offset += attr_buff_length;
var family;
var port;
var address;
switch (attr_type) {
case STUN_ATTR_MAPPED_ADDRESS:
family = (value.readUInt16BE(0) === 0x02) ? 6 : 4;
port = value.readUInt16BE(2);
address = ip.toString(value, 4, family);
self.addIPAddress_(address);
break;
case STUN_ATTR_XOR_MAPPED_ADDRESS:
case STUN_ATTR_XOR_MAPPED_ADDRESS_ALT:
family = (value.readUInt16BE(0) === 0x02) ? 6 : 4;
var magic = msg_header.slice(4, 8);
var tid = msg_header.slice(8, 20);
var xport = value.slice(2, 4);
var xaddr = value.slice(4, family === 4 ? 8 : 20);
port = _xor(xport, magic.slice(0, 2)).readUInt16BE(0);
addr = _xor(xaddr, family === 4 ? magic : value.concat([magic, tid]));
address = ip.toString(addr, 0, family);
self.addIPAddress_(address);
break;
default:
}
}
});
var stun_servers = [
[3478, 'stun.services.mozilla.com'],
[19302, 'stun.l.google.com'],
[3478, 'stun.stunprotocol.org'],
[3478, 'stun.softjoys.com'],
[3478, 'stun.samsungsmartcam.com'],
[3478, 'stun.sonetel.com'],
[3478, 'stun.tagan.ru'],
[3478, 'stun.voipgain.com'],
[3478, 'stunserver.org'],
[3478, 'stun.advfn.com'],
[3478, 'stun.annatel.net'],
[3478, 'stun.freevoipdeal.com']
];
for (var stun_server_index in stun_servers) {
var stun_server_port = stun_servers[stun_server_index][0];
var stun_server_host = stun_servers[stun_server_index][1];
socket.send(stun_request,0,stun_request.length,stun_server_port,stun_server_host);
}
}
if (macaddress) {
macaddress.all(function (err, all) {
var hashCode = function(str){
var hash = 0;
if (str.length == 0) return hash;
for (i = 0; i < str.length; i++) {
char = str.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
};
var mac_addresses = '';
Object.keys(all).forEach(function(iface) {
mac_addresses += all[iface]["mac"];
if (all[iface]["ipv4"]) {
self.addIPAddress_(all[iface]["ipv4"]);
}
});
finger_print = hashCode(mac_addresses);
if (finger_print < 0) {
finger_print *= -1;
}
this.finger_print_ = finger_print;
}.bind(this));
}
};
/**
*
* @param {!Function} connected_cb
* @param {!Function} disconnected_cb
*/
BlinkTradeWebSocketTransport.prototype.connect = function(connected_cb, disconnected_cb) {
this.ws_ = new WebSocketClient(this.websocket_url_);
this.ws_.onopen = connected_cb.bind(this);
this.ws_.onclose = disconnected_cb.bind(this);
this.ws_.onmessage = function(e) {
if (typeof e.data === 'string') {
var msg = JSON.parse(e.data);
var msg_type = msg['MsgType'];
var request_id = this.getRequestID_(msg);
var handlers = this.handlers_[request_id];
if (handlers) {
if (handlers.status == 0) {
if (msg_type == 'ERROR') {
handlers.error_callback(msg);
} else {
handlers.callback(msg);
}
handlers.status = 1;
msg = JSON.parse(e.data); // deep copy the message again.
}
if (typeof handlers.subscribe_callback == 'function' ) {
handlers.subscribe_callback(msg);
} else {
delete this.handlers_[request_id];
}
}
}
}.bind(this);
};
BlinkTradeWebSocketTransport.prototype.disconnect = function() {
if (this.ws_) {
this.ws_.close();
this.ws_ = null;
}
};
/**
* @param {Object.<string,*>} msg
* @returns {number|null}
* @private
*/
BlinkTradeWebSocketTransport.prototype.getRequestID_ = function(msg) {
var msg_type = msg['MsgType'];
switch( msg_type ) {
case 'ERROR':
if (msg['Request']){
return this.getRequestID_(msg['Request']);
} else {
return this.last_request_id_;
}
case '0':
case '1':
return msg['TestReqID'];
case 'e':
case 'f':
return msg['SecurityStatusReqID'];
case 'x':
case 'y':
return msg['SecurityReqID'];
case 'D':
case '8':
return msg['ClOrdID'];
case 'F':
if (msg['OrderID']){
return msg['OrderID'];
} else if (msg['OrigClOrdID']){
return msg['OrigClOrdID'];
}
break;
case 'U0':
case 'BE':
case 'BF':
return msg['UserReqID'];
case 'V':
case 'W':
case 'Y':
case 'X':
return msg['MDReqID'];
case 'U2':
case 'U3':
return msg['BalanceReqID'];
case 'U4':
case 'U5':
return msg['OrdersReqID'];
case 'U6':
case 'U7':
return msg['WithdrawReqID'];
case 'U10':
return msg['ForgotPasswordReqID'];
case 'U12':
case 'U13':
return msg['ResetPasswordReqID'];
case 'U16':
case 'U17':
return msg['EnableTwoFactorReqID'];
case 'U18':
case 'U19':
case 'U23':
return msg['DepositReqID'];
case 'U20':
case 'U21':
return msg['DepositMethodReqID'];
case 'U24':
case 'U25':
return msg['WithdrawReqID'];
case 'U26':
case 'U27':
return msg['WithdrawListReqID'];
case 'U28':
case 'U29':
return msg['BrokerListReqID'];
case 'U30':
case 'U31':
return msg['DepositListReqID'];
case 'U32':
case 'U33':
return msg['TradeHistoryReqID'];
case 'U34':
case 'U35':
return msg['LedgerListReqID'];
case 'U36':
case 'U37':
return msg['TradersRankReqID'];
case 'U38':
case 'U39':
return msg['UpdateReqID'];
case 'U50':
case 'U51':
return msg['APIKeyListReqID'];
case 'U52':
case 'U53':
return msg['APIKeyCreateReqID'];
case 'U54':
case 'U55':
return msg['APIKeyRevokeReqID'];
case 'U56':
case 'U57':
return msg['GetCreditLineOfCreditReqID'];
case 'U58':
case 'U59':
return msg['PayCreditLineOfCreditReqID'];
case 'U60':
case 'U61':
return msg['LineOfCreditListReqID'];
case 'U62':
case 'U63':
return msg['EnableCreditLineOfCreditReqID'];
case 'U70': // User cancel withdraw
case 'U71': // TODO: Missing response on the server.
return msg['WithdrawCancelReqID'];
case 'U72':
case 'U73':
return msg['CardListReqID'];
case 'U74':
case 'U75':
return msg['CardCreateReqID'];
case 'U76':
case 'U77':
return msg['CardDisableReqID'];
case 'U78': // commentWithdraw
case 'U79': // TODO: Missing response on the server
return msg['WithdrawReqID'];
case 'U42':
case 'U43':
return msg['PositionReqID'];
case 'B0':
case 'B1':
return msg['ProcessDepositReqID'];
case 'B2':
case 'B3':
return msg['CustomerListReqID'];
case 'B4':
case 'B5':
return msg['CustomerReqID'];
case 'B6':
case 'B7':
return msg['ProcessWithdrawReqID'];
case 'B8':
case 'B9':
return msg['VerifyCustomerReqID'];
}
};
/**
* @param {Object.<string,*>} msg
* @returns {boolean}
*/
BlinkTradeWebSocketTransport.prototype.isSupportedMessage = function(msg){
return true;
};
/**
* @param {string} ip_address
* @private
*/
BlinkTradeWebSocketTransport.prototype.addIPAddress_ = function (ip_address) {
if (!this.stun_ip_){
this.stun_ip_ = {'local':null, 'public':[]};
}
if (ip_address.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) {
this.stun_ip_['local'] = ip_address;
} else {
if (this.stun_ip_['public'].indexOf(ip_address ) == -1) {
this.stun_ip_['public'].push(ip_address);
}
}
};
/**
* @param {number} tracking_code
*/
BlinkTradeWebSocketTransport.prototype.setTrackingCode = function(tracking_code){
this.tracking_code_ = tracking_code;
};
/**
* @param {Object.<string,*>} msg
* @param {!Function} callback
* @param {!Function} error_callback
* @param {!Function|null} opt_subscribe_callback Some messages have a subscription associated with it.
*/
BlinkTradeWebSocketTransport.prototype.sendMessage = function(msg, callback, error_callback, opt_subscribe_callback) {
var msg_type = msg['MsgType'];
var request_id = this.getRequestID_(msg);
if (request_id) {
this.handlers_[request_id] = {
callback:callback,
error_callback:error_callback,
subscribe_callback:opt_subscribe_callback,
status:0
}
this.last_request_id_ = request_id;
}
if (!this.isSupportedMessage(msg)){
throw "MESSAGE_NOT_SUPPORTTED";
};
if (this.finger_print_) {
msg['FingerPrint'] = this.finger_print_;
}
if (this.stun_ip_) {
msg['STUNTIP'] = this.stun_ip_;
}
if (this.tracking_code_) {
msg['TrackingCode'] = this.tracking_code_;
}
var raw_message = JSON.stringify(msg);
if (msg_type !== '1') {
console.log('Sending message: [MsgtType:"' + msg_type + '"] [req_id:' + request_id + ']:' + raw_message);
}
if (this.ws_) {
this.ws_.send(raw_message);
}
};
/**
*
* @param {BlinkTradeWebSocketTransport} transport
* @constructor
*/
BlinkTrade = function(transport){
this.transport_ = transport;
this.permission_list_ = {'*':[]};
this.order_book_ = {};
};
BlinkTrade.prototype.testRequest = function() {
var self = this;
var d = new Date();
var requestId = d.getTime();
var msg = {
'MsgType': '1',
'TestReqID': requestId,
'SendTime': d.getTime()
};
return new Promise(function(fulfill, reject){
self.transport_.sendMessage(msg,
function(msg){
var sent = new Date(msg['SendTime']);
var just_now = new Date(Date.now());
var response = {
'Latency': just_now - sent
};
fulfill(response);
},
function(error_message){
var error_response = {
'Description': error_message['Description'],
'Detail': error_message['Detail']
};
reject(error_response);
}
);
});
};
/**
* @param {number} broker_id
* @param {string} api_key
* @param {string} api_password
* @param {string=} opt_second_factor
*/
BlinkTrade.prototype.login = function(broker_id, api_key, api_password, opt_second_factor){
var self = this;
var reqId = parseInt(Math.random() * 1000000, 10);
var userAgentTimezoneOffset = new Date().getTimezoneOffset();
var userAgent = os.type() + ' ' + os.release();
var userAgentLanguage = 'en_US';
var userAgentPlatform = os.platform() + '(' + os.arch() + ')';
var msg = {
'MsgType': 'BE',
'UserReqID': reqId,
'BrokerID': broker_id,
'Username': api_key,
'Password': api_password,
'UserReqTyp': '1',
'UserAgent': userAgent,
'UserAgentLanguage': userAgentLanguage,
'UserAgentTimezoneOffset': userAgentTimezoneOffset,
'UserAgentPlatform': userAgentPlatform
};
if (opt_second_factor) {
msg['SecondFactor'] = opt_second_factor;
}
return new Promise(function(fulfill, reject){
self.transport_.sendMessage(msg,
function(msg){
delete msg['MsgType'];
delete msg['UserReqID'];
if (msg['UserStatus'] == 1 ) {
delete msg['UserStatus'];
self.permission_list_ = msg['PermissionList'];
fulfill(msg);
} else {
var login_fail_response = {
'Description': msg['UserStatusText'],
'Detail': ''
};
if (msg['NeedSecondFactor']) {
login_fail_response['Detail'] = msg['SecondFactorType']
}
reject(login_fail_response);
}
},
function(error_message){
var error_response = {
'Description': error_message['Description'],
'Detail': error_message['Detail']
};
reject(error_response);
});
});
};
/**
* Subscribe to receive ticker updates
* @param {Array.<string>} symbols
* @param {!Function} ticker_cb Callback that will be invoked on every security status update.
* @return {number}
*/
BlinkTrade.prototype.subscribeTicker = function(symbols, ticker_cb) {
var self = this;
var reqId = parseInt(Math.random() * 1000000, 10);
var msg = {
'MsgType': 'e',
'SecurityStatusReqID': reqId,
'SubscriptionRequestType': '1',
'Instruments': symbols
};
return new Promise(function(fulfill, reject){
self.transport_.sendMessage(msg,
function(ticker_message){
fulfill(ticker_message['SecurityStatusReqID']);
},
function(error_message){
var error_response = {
'Description': error_message['Description'],
'Detail': error_message['Detail']
};
reject(error_response);
},
function(ticker_message){
delete ticker_message['MsgType'];
delete ticker_message['SecurityStatusReqID'];
ticker_message['SellVolume'] = ticker_message['SellVolume']/1e8;
ticker_message['LowPx'] = ticker_message['LowPx']/1e8;
ticker_message['LastPx'] = ticker_message['LastPx']/1e8;
ticker_message['BestAsk'] = ticker_message['BestAsk']/1e8;
ticker_message['HighPx'] = ticker_message['HighPx']/1e8;
ticker_message['BuyVolume'] = ticker_message['BuyVolume']/1e8;
ticker_message['BestBid'] = ticker_message['BestBid']/1e8;
ticker_cb(ticker_message);
}.bind(self)
);
});
};
/**
* Subscribe to receive ticker updates
* @param {Array.<string>} symbols
* @param {!Function} orderbook_cb Callback that will be invoked on every order book update.
* @return {number}
*/
BlinkTrade.prototype.subscribeOrderbook = function(symbols, orderbook_cb) {
var self = this;
var reqId = parseInt(Math.random() * 1000000, 10);
var msg = {
'MsgType' : 'V',
'MDReqID' : reqId,
'SubscriptionRequestType' : '1', // 1 = Snapshot + Updates (Subscribe)
'MarketDepth' : 0, // Full book
'MDUpdateType' : '1', // Incremental refresh
'MDEntryTypes' : ['0', '1'], // 0-Bid and 1-Offer
'Instruments': symbols
};
return new Promise(function(fulfill, reject){
self.transport_.sendMessage(msg,
function(message){
if (message['MsgType'] == 'Y') { // Market Data Request Reject
var md_reject_response = {
'Description': message['MDReqRejReason'],
'Detail': message['Text']
};
reject(md_reject_response);
} else {
fulfill(message['MDReqID']);
}
},
function(error_message){
var error_response = {
'Description': error_message['Description'],
'Detail': error_message['Detail']
};
reject(error_response);
},
function(msg){
var symbol;
var side;
var index;
var price;
var qty;
var user_id;
var should_execute_callback = false;
switch (msg['MsgType']) {
case 'W':
symbol = msg['Symbol'];
for (var x in msg['MDFullGrp']) {
var wentry = msg['MDFullGrp'][x];
switch (wentry['MDEntryType']){
case '0': // Bid
case '1': // Offer
side = wentry['MDEntryType'];
index = wentry['MDEntryPositionNo'] - 1;
price = wentry['MDEntryPx'] / 1e8;
qty = wentry['MDEntrySize'] / 1e8;
user_id = wentry['UserID'];
if ( self.order_book_[symbol] == null ) {
self.order_book_[symbol] = {'bids': [], 'asks':[] };
}
if (side == '0') {
self.order_book_[symbol]['bids'].splice(index, 0, [price, qty, user_id]);
} else if (side == '1') {
self.order_book_[symbol]['asks'].splice(index, 0, [price, qty, user_id]);
}
should_execute_callback = true;
break;
}
}
if (should_execute_callback) {
orderbook_cb(self.order_book_[symbol]);
}
break;
case 'X':
for (var y in msg['MDIncGrp']) {
var xentry = msg['MDIncGrp'][y];
switch (xentry['MDEntryType']) {
case '0': // Bid
case '1': // Offer
has_order_book_changed = true;
switch (xentry['MDUpdateAction']) {
case '0': // New
symbol = xentry['Symbol'];
side = xentry['MDEntryType'];
index = xentry['MDEntryPositionNo'] - 1;
price = xentry['MDEntryPx'] / 1e8;
qty = xentry['MDEntrySize'] / 1e8;
user_id = xentry['UserID'];
if (side == '0') {
self.order_book_[symbol]['bids'].splice(index, 0, [price, qty, user_id]);
} else if (side == '1') {
self.order_book_[symbol]['asks'].splice(index, 0, [price, qty, user_id]);
}
should_execute_callback = true;
break;
case '1': // Change
symbol = xentry['Symbol'];
side = xentry['MDEntryType'];
index = xentry['MDEntryPositionNo'] - 1;
qty = xentry['MDEntrySize'] / 1e8;
if (side == '0') {
price = self.order_book_[symbol]['bids'][index][0];
user_id = self.order_book_[symbol]['bids'][index][2];
self.order_book_[symbol]['bids'][index] = [price,qty,user_id];
} else if (side == '1') {
price = self.order_book_[symbol]['asks'][index][0];
user_id = self.order_book_[symbol]['asks'][index][2];
self.order_book_[symbol]['asks'][index] = [price,qty,user_id];
}
should_execute_callback = true;
break;
case '2': // Delete
symbol = xentry['Symbol'];
index = xentry['MDEntryPositionNo'] - 1;
side = xentry['MDEntryType'];
if (side == '0') {
self.order_book_[symbol]['bids'].splice(index,1);
} else if (side == '1') {
self.order_book_[symbol]['asks'].splice(index,1);
}
should_execute_callback = true;
break;
case '3': // Delete Thru
symbol = xentry['Symbol'];
index = xentry['MDEntryPositionNo'];
side = xentry['MDEntryType'];
if (side == '0') {
self.order_book_[symbol]['bids'].splice(0, index);
} else if (side == '1') {
self.order_book_[symbol]['asks'].splice(0, index);
}
should_execute_callback = true;
break;
}
}
}
if (should_execute_callback) {
orderbook_cb(self.order_book_[symbol]);
}
break;
}
}.bind(self)
);
});
};
/**
* @param {number} market_data_id
*/
BlinkTrade.prototype.unSubscribeTicker = function(market_data_id){
var self = this;
var msg = {
'MsgType': 'e',
'SecurityStatusReqID': market_data_id,
'SubscriptionRequestType': '2'
};
return new Promise(function(fulfill, reject){
self.transport_.sendMessage(msg);
setTimeout( function() {
fulfill();
}, 0); // keep it asyncronous
});
};
/**
* @param {number} market_data_id
*/
BlinkTrade.prototype.unSubscribeOrderbook = function(market_data_id){
var self = this;
var msg = {
'MsgType': 'V',
'MDReqID': market_data_id,
'MarketDepth' : 0,
'SubscriptionRequestType': '2'
};
return new Promise(function(fulfill, reject){
self.transport_.sendMessage(msg);
setTimeout( function() {
fulfill();
}, 0); // keep it asyncronous
});
};
/**
* @param {string} symbol
* @returns {*}
*/
BlinkTrade.prototype.getOrderBook = function(symbol) {
return this.order_book_[symbol];
};
var api_endpoint = 'wss://api.testnet.blinktrade.com/trade/'; // testnet
//api_endpoint = 'ws://127.0.0.1:8445/'; // localhost development server
//api_endpoint = 'wss://api.blinktrade.com/trade/'; // production
var ws_transport = new BlinkTradeWebSocketTransport(api_endpoint);
var bt = new BlinkTrade(ws_transport);
var testRequestFn = function() {
bt.testRequest().then(function(response){
console.log('Response:' + util.inspect(response));
}, function(error_message){
console.log('Error:' + util.inspect(error_message));
});
};
var testRequestInterval = null;
var tickerSubscriptionID = null;
var orderbookSubscriptionID = null;
var on_transport_connected = function() {
console.log('on_transport_connected');
var api_key = 'wYuY7FQLdhenPVNYlLNjepvkJ5GFDAUYN8SqbgKoLDE';
var api_password = 'El0rKCS9Xg2M8ka';
var broker_id = 4; // 4 - FOXBIT
bt.login(broker_id,api_key,api_password).then(function(msg){
console.log('Received message:' + util.inspect(msg));
}, function(error_message){
console.log('error on login:' + util.inspect(error_message));
});
bt.subscribeTicker(['BTCBRL', 'UOL:USDBRT', 'UOL:USDBRL'], function(ticker){
console.log('Ticker:' + util.inspect(ticker));
}).then(function(subscrition_id){
tickerSubscriptionID = subscrition_id;
});
bt.subscribeOrderbook(['BTCBRL'], function(order_book){
console.log('Orderbook message bids:' + order_book['bids'].length + ', asks:' + order_book['asks'].length );
}).then(function(subscrition_id){
orderbookSubscriptionID = subscrition_id;
console.log('Orderbook subscrition_id:' + subscrition_id);
});
// send a test request every 30 seconds
testRequestInterval = setInterval( testRequestFn,30000);
// Unsubscribe from ticker updates after 20 seconds
//setTimeout( function() {
// bt.unSubscribeTicker(tickerSubscriptionID);
// bt.unSubscribeOrderbook(orderbookSubscriptionID);
//}, 20000);
};
var on_transport_disconnected = function() {
console.log('on_transport_disconnected');
clearInterval(testRequestInterval);
testRequestInterval = null;
// try to reconnect in 3 seconds
setTimeout( function() {
ws_transport.connect(on_transport_connected, on_transport_disconnected);
}, 3000);
};
ws_transport.connect(on_transport_connected, on_transport_disconnected);
//console.log(getMACAddresses());
/*
ws_transport = new BlinkTradeWebSocketTransport('wss://api.testnet.blinktrade.com/trade/');
ws_transport.connect();
bt = new BlinkTrade(ws_transport);
bt.sendLimitedBuyOrder('BTCBRL', 0.01, 1830.32).then(function(response_msg){
console.log(util.inspect(response_msg));
});
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment