From c030d2480dcaa422a40fb3cc99206063b822b51c Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 1 Apr 2016 17:02:14 -0700 Subject: [PATCH] more http. --- lib/bcoin/http/client.js | 74 +++++++++++++++++++++++++++++++++++---- lib/bcoin/http/http.js | 34 +++++++++++++++++- lib/bcoin/http/request.js | 10 +++--- lib/bcoin/http/server.js | 17 +++++++-- lib/bcoin/wallet.js | 25 +++++++++++++ 5 files changed, 144 insertions(+), 16 deletions(-) diff --git a/lib/bcoin/http/client.js b/lib/bcoin/http/client.js index 710153ce..40390c78 100644 --- a/lib/bcoin/http/client.js +++ b/lib/bcoin/http/client.js @@ -6,6 +6,7 @@ var EventEmitter = require('events').EventEmitter; var bcoin = require('../../bcoin'); +var network = bcoin.protocol.network; var utils = require('../utils'); var request = require('./request'); @@ -13,15 +14,19 @@ var request = require('./request'); * Client */ -function Client(uri) { +function Client(uri, options) { if (!(this instanceof Client)) - return new Client(uri); + return new Client(uri, options); + + if (!options) + options = {}; EventEmitter.call(this); this.uri = uri; this.loaded = false; this.id = null; + this.options = options; this._init(); } @@ -43,6 +48,13 @@ Client.prototype._init = function _init() { this.socket = new io.Socket(this.uri); this.socket.on('open', function() { + self.socket.on('version', function(info) { + utils.debug('Connected to bcoin server: %s (%s)', + info.version, info.network); + if (self.options.setNetwork) + network.set(info.network); + }); + self.socket.on('tx', function(tx, map) { try { tx = bcoin.tx.fromJSON(tx); @@ -105,10 +117,16 @@ Client.prototype.open = function open(callback) { }; Client.prototype.listenWallet = function listenWallet(id) { + if (!this.socket) + return; + this.socket.join(id); }; Client.prototype.unlistenWallet = function unlistenWallet(id) { + if (!this.socket) + return; + this.socket.leave(id); }; @@ -134,7 +152,9 @@ Client.prototype.destroy = function destroy(callback) { }; Client.prototype._request = function _request(method, endpoint, json, callback) { + var self = this; var query; + var networkType; if (!callback) { callback = json; @@ -142,13 +162,13 @@ Client.prototype._request = function _request(method, endpoint, json, callback) } if (json && method === 'get') { - json = null; query = json; + json = true; } request({ method: method, - uri: this.uri + '/' + endpoint, + uri: this.uri + endpoint, query: query, json: json, expect: 'json' @@ -156,6 +176,12 @@ Client.prototype._request = function _request(method, endpoint, json, callback) if (err) return callback(err); + if (self.options.setNetwork) { + networkType = res.headers['x-bcoin-network']; + if (networkType && network.type !== networkType) + network.set(networkType); + } + if (res.statusCode === 404) return callback(); @@ -198,6 +224,7 @@ Client.prototype._getWallet = function getWallet(id, callback) { }; Client.prototype.getWallet = function getWallet(id, passphrase, callback) { + var self = this; var provider; return this._getWallet(id, function(err, json) { @@ -217,7 +244,8 @@ Client.prototype.getWallet = function getWallet(id, passphrase, callback) { }; Client.prototype.createWallet = function createWallet(options, callback) { - return this._createWallet(options, function(err) { + var self = this; + return this._createWallet(options, function(err, json) { if (err) return callback(err); @@ -302,8 +330,8 @@ Client.prototype.getWalletBalance = function getBalance(id, callback) { return callback(new Error('Not found.')); return callback(null, { - confirmed: utils.satoshi(body.balance.confirmed), - unconfirmed: utils.satoshi(body.balance.unconfirmed) + confirmed: utils.satoshi(body.confirmed), + unconfirmed: utils.satoshi(body.unconfirmed) }); }); }; @@ -563,6 +591,38 @@ Client.prototype.zapWallet = function zapWallet(id, now, age, callback) { }); }; +Client.prototype.getMempool = function getMempool(callback) { + return this._get('/mempool', function(err, body) { + if (err) + return callback(err); + + if (!body) + return callback(null, []); + + try { + body = body.map(function(data) { + return bcoin.tx.fromJSON(data); + }); + } catch (e) { + return callback(e); + } + + return callback(null, body); + }); +}; + +Client.prototype.getInfo = function getInfo(callback) { + return this._get('/', function(err, body) { + if (err) + return callback(err); + + if (!body) + return callback(new Error('Info not available.')); + + return callback(null, body); + }); +}; + /** * Expose */ diff --git a/lib/bcoin/http/http.js b/lib/bcoin/http/http.js index 31cb93cd..3eae7ef8 100644 --- a/lib/bcoin/http/http.js +++ b/lib/bcoin/http/http.js @@ -99,8 +99,9 @@ HTTPServer.prototype._initRouter = function _initRouter() { req.destroy(); req.socket.destroy(); } catch (e) { - ; + utils.debug(e.stack + ''); } + utils.debug(err.stack + ''); } } @@ -208,22 +209,53 @@ HTTPServer.prototype.use = function use(path, callback) { path = null; } + if (Array.isArray(path)) { + path.forEach(function(path) { + this.use(path, callback); + }, this); + return; + } + this.stack.push({ path: path, callback: callback }); }; HTTPServer.prototype.get = function get(path, callback) { + if (Array.isArray(path)) { + path.forEach(function(path) { + this.get(path, callback); + }, this); + return; + } this.routes.get.push({ path: path, callback: callback }); }; HTTPServer.prototype.post = function post(path, callback) { + if (Array.isArray(path)) { + path.forEach(function(path) { + this.post(path, callback); + }, this); + return; + } this.routes.post.push({ path: path, callback: callback }); }; HTTPServer.prototype.put = function put(path, callback) { + if (Array.isArray(path)) { + path.forEach(function(path) { + this.put(path, callback); + }, this); + return; + } this.routes.put.push({ path: path, callback: callback }); }; HTTPServer.prototype.del = function del(path, callback) { + if (Array.isArray(path)) { + path.forEach(function(path) { + this.del(path, callback); + }, this); + return; + } this.routes.del.push({ path: path, callback: callback }); }; diff --git a/lib/bcoin/http/request.js b/lib/bcoin/http/request.js index 77f57524..28a5857b 100644 --- a/lib/bcoin/http/request.js +++ b/lib/bcoin/http/request.js @@ -84,6 +84,11 @@ function request(options, callback, stream) { type = 'binary'; } + if (type === 'json' && typeof body === 'object') + body = JSON.stringify(body); + else if (type === 'form' && typeof body === 'object') + body = qs.stringify(body); + if (type === 'form') type = 'application/x-www-form-urlencoded; charset=utf-8'; else if (type === 'json') @@ -93,11 +98,6 @@ function request(options, callback, stream) { else if (type === 'binary') type = 'application/octet-stream'; - if (type === 'json' && typeof body === 'object') - body = JSON.stringify(body); - else if (type === 'form' && typeof body === 'object') - body = qs.stringify(body); - if (typeof body === 'string') body = new Buffer(body, 'utf8'); diff --git a/lib/bcoin/http/server.js b/lib/bcoin/http/server.js index 7c96e5ff..eb385d7f 100644 --- a/lib/bcoin/http/server.js +++ b/lib/bcoin/http/server.js @@ -6,6 +6,8 @@ var EventEmitter = require('events').EventEmitter; var bcoin = require('../../bcoin'); +var constants = bcoin.protocol.constants; +var network = bcoin.protocol.network; var HTTPServer = require('./http'); var utils = require('../utils'); var assert = utils.assert; @@ -47,6 +49,9 @@ NodeServer.prototype._init = function _init() { return res.end(); } + res.setHeader('X-Bcoin-Network', network.type); + res.setHeader('X-Bcoin-Version', constants.userAgent); + next(); }); @@ -164,7 +169,7 @@ NodeServer.prototype._init = function _init() { // Bulk read UTXOs this.post('/coin/address', function(req, res, next, send) { - self.node.getCoinsByAddress(req.body.addresses, function(err, coins) { + self.node.getCoinsByAddress(req.options.addresses, function(err, coins) { if (err) return next(err); @@ -207,7 +212,7 @@ NodeServer.prototype._init = function _init() { // Bulk read TXs this.post('/tx/address', function(req, res, next, send) { - self.node.getTXByAddress(req.body.addresses, function(err, txs) { + self.node.getTXByAddress(req.options.addresses, function(err, txs) { if (err) return next(err); @@ -248,7 +253,7 @@ NodeServer.prototype._init = function _init() { }); // Create/get wallet - this.post('/wallet/:id', function(req, res, next, send) { + this.post(['/wallet', '/wallet/:id'], function(req, res, next, send) { self.walletdb.create(req.options, function(err, wallet) { var json; @@ -507,7 +512,13 @@ NodeServer.prototype._initIO = function _initIO() { socket.on('error', function(err) { self.emit('error', err); }); + self.emit('websocket', socket); + + socket.emit('version', { + version: constants.userAgent, + network: network.type + }); }); this.walletdb.on('tx', function(tx, map) { diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 73192f6e..ab2b678f 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -1012,6 +1012,31 @@ Wallet.prototype.__defineGetter__('address', function() { return this.getAddress(); }); +Wallet.prototype.inspect = function inspect() { + return { + id: this.id, + type: this.type, + network: network.type, + m: this.m, + n: this.n, + keyAddress: this.keyAddress, + scriptAddress: this.scriptAddress, + programAddress: this.programAddress, + witness: this.witness, + derivation: this.derivation, + copayBIP45: this.copayBIP45, + accountIndex: this.accountIndex, + receiveDepth: this.receiveDepth, + changeDepth: this.changeDepth, + master: this.master.toJSON(this.options.passphrase), + accountKey: this.accountKey.xpubkey, + addressMap: this.addressMap, + keys: this.keys.map(function(key) { + return key.xpubkey; + }) + }; +}; + Wallet.prototype.toJSON = function toJSON() { return { v: 3,