Web service and other changes in preparation for insight-api
This commit is contained in:
parent
854f98fe43
commit
a68cf4ecf8
|
@ -10,6 +10,7 @@ var index = require('./');
|
|||
var log = index.log;
|
||||
var Bus = require('./bus');
|
||||
var BaseService = require('./service');
|
||||
var WebService = require('./web');
|
||||
|
||||
function Node(config) {
|
||||
if(!(this instanceof Node)) {
|
||||
|
|
|
@ -82,102 +82,7 @@ function start(options) {
|
|||
});
|
||||
|
||||
node.on('ready', function() {
|
||||
|
||||
var io = socketio(fullConfig.port);
|
||||
|
||||
io.on('connection', function(socket) {
|
||||
|
||||
var bus = node.openBus();
|
||||
|
||||
var methods = node.getAllAPIMethods();
|
||||
var methodsMap = {};
|
||||
|
||||
methods.forEach(function(data) {
|
||||
var name = data[0];
|
||||
var instance = data[1];
|
||||
var method = data[2];
|
||||
var args = data[3];
|
||||
methodsMap[name] = {
|
||||
fn: function() {
|
||||
return method.apply(instance, arguments);
|
||||
},
|
||||
args: args
|
||||
};
|
||||
});
|
||||
|
||||
socket.on('message', function(message, socketCallback) {
|
||||
if (methodsMap[message.method]) {
|
||||
var params = message.params;
|
||||
|
||||
if(!params || !params.length) {
|
||||
params = [];
|
||||
}
|
||||
|
||||
if(params.length !== methodsMap[message.method].args) {
|
||||
return socketCallback({
|
||||
error: {
|
||||
message: 'Expected ' + methodsMap[message.method].args + ' parameters'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var callback = function(err, result) {
|
||||
var response = {};
|
||||
if(err) {
|
||||
response.error = {
|
||||
message: err.toString()
|
||||
};
|
||||
}
|
||||
|
||||
if(result) {
|
||||
response.result = result;
|
||||
}
|
||||
|
||||
socketCallback(response);
|
||||
};
|
||||
|
||||
params = params.concat(callback);
|
||||
methodsMap[message.method].fn.apply(this, params);
|
||||
} else {
|
||||
socketCallback({
|
||||
error: {
|
||||
message: 'Method Not Found'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('subscribe', function(name, params) {
|
||||
bus.subscribe(name, params);
|
||||
});
|
||||
|
||||
socket.on('unsubscribe', function(name, params) {
|
||||
bus.unsubscribe(name, params);
|
||||
});
|
||||
|
||||
var events = node.getAllPublishEvents();
|
||||
|
||||
events.forEach(function(event) {
|
||||
bus.on(event.name, function() {
|
||||
if(socket.connected) {
|
||||
var results = [];
|
||||
|
||||
for(var i = 0; i < arguments.length; i++) {
|
||||
results.push(arguments[i]);
|
||||
}
|
||||
|
||||
var params = [event.name].concat(results);
|
||||
socket.emit.apply(socket, params);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('disconnect', function() {
|
||||
bus.close();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
log.info('Bitcore Node ready');
|
||||
});
|
||||
|
||||
node.on('error', function(err) {
|
||||
|
@ -207,7 +112,12 @@ function start(options) {
|
|||
if(err.stack) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
node.stop(function(err) {
|
||||
if(err) {
|
||||
log.error('Failed to stop services: ' + err);
|
||||
}
|
||||
process.exit(-1);
|
||||
});
|
||||
}
|
||||
if (options.sigint) {
|
||||
node.stop(function(err) {
|
||||
|
|
|
@ -24,7 +24,9 @@ Service.dependencies = [];
|
|||
*/
|
||||
Service.prototype.blockHandler = function(block, add, callback) {
|
||||
// implement in the child class
|
||||
setImmediate(callback);
|
||||
setImmediate(function() {
|
||||
callback(null, []);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -57,12 +59,26 @@ Service.prototype.getAPIMethods = function() {
|
|||
//
|
||||
// };
|
||||
|
||||
/**
|
||||
* Function which is called when module is first initialized
|
||||
*/
|
||||
Service.prototype.start = function(done) {
|
||||
setImmediate(done);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to be called when bitcore-node is stopped
|
||||
*/
|
||||
Service.prototype.stop = function(done) {
|
||||
setImmediate(done);
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup express routes
|
||||
* @param {Express} app
|
||||
*/
|
||||
Service.prototype.setupRoutes = function(app) {
|
||||
// Setup express routes here
|
||||
};
|
||||
|
||||
module.exports = Service;
|
||||
|
|
|
@ -505,6 +505,7 @@ AddressService.prototype.getAddressHistoryForAddress = function(address, queryMe
|
|||
var confirmations = 0;
|
||||
if(transaction.__height >= 0) {
|
||||
confirmations = self.node.services.db.tip.__height - transaction.__height;
|
||||
confirmations = self.node.services.db.tip.__height - transaction.__height + 1;
|
||||
}
|
||||
|
||||
txinfos[transaction.hash] = {
|
||||
|
|
|
@ -217,6 +217,7 @@ DB.prototype.getTransactionWithBlockInfo = function(txid, queryMempool, callback
|
|||
}
|
||||
|
||||
var tx = Transaction().fromBuffer(obj.buffer);
|
||||
tx.__blockHash = obj.blockHash;
|
||||
tx.__height = obj.height;
|
||||
tx.__timestamp = obj.timestamp;
|
||||
|
||||
|
@ -657,6 +658,7 @@ DB.prototype.sync = function() {
|
|||
|
||||
self.bitcoindSyncing = false;
|
||||
self.lastSavedMetadataThreshold = 0;
|
||||
self.chain.saveMetadata();
|
||||
|
||||
// If bitcoind is completely synced
|
||||
if (self.node.services.bitcoind.isSynced()) {
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
'use strict';
|
||||
|
||||
var http = require('http');
|
||||
var express = require('express');
|
||||
var bodyParser = require('body-parser');
|
||||
var socketio = require('socket.io');
|
||||
|
||||
var WebService = function(options) {
|
||||
var self = this;
|
||||
this.node = options.node;
|
||||
this.port = options.port || 3456;
|
||||
|
||||
this.node.on('ready', function() {
|
||||
self.setupRoutes();
|
||||
self.server.listen(self.port);
|
||||
});
|
||||
};
|
||||
|
||||
WebService.prototype.start = function(callback) {
|
||||
var self = this;
|
||||
this.app = express();
|
||||
this.app.use(bodyParser.json());
|
||||
|
||||
this.server = http.createServer(this.app);
|
||||
|
||||
this.io = socketio.listen(this.server);
|
||||
this.io.on('connection', this.socketHandler.bind(this));
|
||||
|
||||
var methods = this.node.getAllAPIMethods();
|
||||
this.methodsMap = {};
|
||||
|
||||
methods.forEach(function(data) {
|
||||
var name = data[0];
|
||||
var instance = data[1];
|
||||
var method = data[2];
|
||||
var args = data[3];
|
||||
self.methodsMap[name] = {
|
||||
fn: function() {
|
||||
return method.apply(instance, arguments);
|
||||
},
|
||||
args: args
|
||||
};
|
||||
});
|
||||
|
||||
setImmediate(callback);
|
||||
};
|
||||
|
||||
WebService.prototype.stop = function(callback) {
|
||||
var self = this;
|
||||
|
||||
setImmediate(function() {
|
||||
if(self.server) {
|
||||
self.server.close();
|
||||
}
|
||||
|
||||
callback();
|
||||
})
|
||||
};
|
||||
|
||||
WebService.prototype.setupRoutes = function() {
|
||||
for(var key in this.node.modules) {
|
||||
this.node.modules[key].setupRoutes(this.app);
|
||||
}
|
||||
};
|
||||
|
||||
WebService.prototype.socketHandler = function(socket) {
|
||||
var self = this;
|
||||
|
||||
var bus = this.node.openBus();
|
||||
|
||||
socket.on('message', this.socketMessageHandler.bind(this));
|
||||
|
||||
socket.on('subscribe', function(name, params) {
|
||||
bus.subscribe(name, params);
|
||||
});
|
||||
|
||||
socket.on('unsubscribe', function(name, params) {
|
||||
bus.unsubscribe(name, params);
|
||||
});
|
||||
|
||||
var events = self.node.getAllPublishEvents();
|
||||
|
||||
events.forEach(function(event) {
|
||||
bus.on(event.name, function() {
|
||||
if(socket.connected) {
|
||||
var results = [];
|
||||
|
||||
for(var i = 0; i < arguments.length; i++) {
|
||||
results.push(arguments[i]);
|
||||
}
|
||||
|
||||
var params = [event.name].concat(results);
|
||||
socket.emit.apply(socket, params);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('disconnect', function() {
|
||||
bus.close();
|
||||
});
|
||||
};
|
||||
|
||||
WebService.prototype.socketMessageHandler = function(message, socketCallback) {
|
||||
if (this.methodsMap[message.method]) {
|
||||
var params = message.params;
|
||||
|
||||
if(!params || !params.length) {
|
||||
params = [];
|
||||
}
|
||||
|
||||
if(params.length !== this.methodsMap[message.method].args) {
|
||||
return socketCallback({
|
||||
error: {
|
||||
message: 'Expected ' + this.methodsMap[message.method].args + ' parameters'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var callback = function(err, result) {
|
||||
var response = {};
|
||||
if(err) {
|
||||
response.error = {
|
||||
message: err.toString()
|
||||
};
|
||||
}
|
||||
|
||||
if(result) {
|
||||
response.result = result;
|
||||
}
|
||||
|
||||
socketCallback(response);
|
||||
};
|
||||
|
||||
params = params.concat(callback);
|
||||
this.methodsMap[message.method].fn.apply(this, params);
|
||||
} else {
|
||||
socketCallback({
|
||||
error: {
|
||||
message: 'Method Not Found'
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = WebService;
|
|
@ -48,11 +48,13 @@
|
|||
"bindings": "^1.2.1",
|
||||
"bitcore": "^0.13.0",
|
||||
"colors": "^1.1.2",
|
||||
"body-parser": "^1.13.3",
|
||||
"commander": "^2.8.1",
|
||||
"errno": "^0.1.4",
|
||||
"leveldown": "^1.4.1",
|
||||
"levelup": "^1.2.1",
|
||||
"liftoff": "^2.1.0",
|
||||
"express": "^4.13.3",
|
||||
"memdown": "^1.0.0",
|
||||
"mkdirp": "0.5.0",
|
||||
"nan": "1.3.0",
|
||||
|
|
|
@ -165,7 +165,7 @@ struct async_block_data {
|
|||
struct async_tx_data {
|
||||
std::string err_msg;
|
||||
std::string txid;
|
||||
std::string blockhash;
|
||||
std::string blockHash;
|
||||
uint32_t nTime;
|
||||
int64_t height;
|
||||
bool queryMempool;
|
||||
|
@ -1235,6 +1235,7 @@ async_get_tx_and_info(uv_work_t *req) {
|
|||
// Read header first to get block timestamp and hash
|
||||
file >> blockHeader;
|
||||
blockHash = blockHeader.GetHash();
|
||||
data->blockHash = blockHash.GetHex();
|
||||
data->nTime = blockHeader.nTime;
|
||||
fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
|
||||
file >> ctx;
|
||||
|
@ -1284,6 +1285,7 @@ async_get_tx_and_info_after(uv_work_t *req) {
|
|||
std::string stx = ssTx.str();
|
||||
Local<Value> rawNodeBuffer = node::Buffer::New(isolate, stx.c_str(), stx.size());
|
||||
|
||||
obj->Set(NanNew<String>("blockHash"), NanNew<String>(data->blockHash));
|
||||
obj->Set(NanNew<String>("height"), NanNew<Number>(data->height));
|
||||
obj->Set(NanNew<String>("timestamp"), NanNew<Number>(data->nTime));
|
||||
obj->Set(NanNew<String>("buffer"), rawNodeBuffer);
|
||||
|
@ -1349,28 +1351,38 @@ NAN_METHOD(GetBlockIndex) {
|
|||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
CBlockIndex* blockIndex;
|
||||
|
||||
if (args[0]->IsNumber()) {
|
||||
int64_t height = args[0]->IntegerValue();
|
||||
blockIndex = chainActive[height];
|
||||
|
||||
if (blockIndex == NULL) {
|
||||
NanReturnValue(Undefined(isolate));
|
||||
}
|
||||
|
||||
} else {
|
||||
String::Utf8Value hash_(args[0]->ToString());
|
||||
std::string hashStr = std::string(*hash_);
|
||||
uint256 hash = uint256S(hashStr);
|
||||
|
||||
CBlockIndex* blockIndex;
|
||||
|
||||
if (mapBlockIndex.count(hash) == 0) {
|
||||
NanReturnValue(Undefined(isolate));
|
||||
} else {
|
||||
blockIndex = mapBlockIndex[hash];
|
||||
}
|
||||
}
|
||||
|
||||
arith_uint256 cw = blockIndex->nChainWork;
|
||||
CBlockIndex* prevBlockIndex = blockIndex->pprev;
|
||||
const uint256* prevHash = prevBlockIndex->phashBlock;
|
||||
|
||||
Local<Object> obj = NanNew<Object>();
|
||||
|
||||
obj->Set(NanNew<String>("hash"), NanNew<String>(blockIndex->phashBlock->GetHex()));
|
||||
obj->Set(NanNew<String>("chainWork"), NanNew<String>(cw.GetHex()));
|
||||
obj->Set(NanNew<String>("prevHash"), NanNew<String>(prevHash->GetHex()));
|
||||
obj->Set(NanNew<String>("height"), NanNew<Number>(blockIndex->nHeight));
|
||||
|
||||
NanReturnValue(obj);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -398,6 +398,7 @@ describe('DB Service', function() {
|
|||
it('should give a transaction with height and timestamp', function(done) {
|
||||
var txBuffer = new Buffer('01000000016f95980911e01c2c664b3e78299527a47933aac61a515930a8fe0213d1ac9abe01000000da0047304402200e71cda1f71e087c018759ba3427eb968a9ea0b1decd24147f91544629b17b4f0220555ee111ed0fc0f751ffebf097bdf40da0154466eb044e72b6b3dcd5f06807fa01483045022100c86d6c8b417bff6cc3bbf4854c16bba0aaca957e8f73e19f37216e2b06bb7bf802205a37be2f57a83a1b5a8cc511dc61466c11e9ba053c363302e7b99674be6a49fc0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9148a31d53a448c18996e81ce67811e5fb7da21e4468738c9d6f90000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000', 'hex');
|
||||
var info = {
|
||||
blockHash: '00000000000ec715852ea2ecae4dc8563f62d603c820f81ac284cd5be0a944d6',
|
||||
height: 530482,
|
||||
timestamp: 1439559434000,
|
||||
buffer: txBuffer
|
||||
|
@ -412,6 +413,7 @@ describe('DB Service', function() {
|
|||
|
||||
db.getTransactionWithBlockInfo('2d950d00494caf6bfc5fff2a3f839f0eb50f663ae85ce092bc5f9d45296ae91f', true, function(err, tx) {
|
||||
should.not.exist(err);
|
||||
tx.__blockHash.should.equal(info.blockHash);
|
||||
tx.__height.should.equal(info.height);
|
||||
tx.__timestamp.should.equal(info.timestamp);
|
||||
done();
|
||||
|
|
Loading…
Reference in New Issue