generators: refactor http.
This commit is contained in:
parent
ae83aa6fba
commit
8c11a2aa3f
13
bin/cli
13
bin/cli
@ -8,6 +8,7 @@ var spawn = require('../lib/utils/spawn');
|
|||||||
var Client = require('../lib/http/client');
|
var Client = require('../lib/http/client');
|
||||||
var Wallet = require('../lib/http/wallet');
|
var Wallet = require('../lib/http/wallet');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
|
var main;
|
||||||
|
|
||||||
function CLI() {
|
function CLI() {
|
||||||
this.config = config({
|
this.config = config({
|
||||||
@ -444,13 +445,11 @@ CLI.prototype.destroy = function destroy() {
|
|||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
function main() {
|
main = co(function* main() {
|
||||||
return spawn(function *() {
|
var cli = new CLI();
|
||||||
var cli = new CLI();
|
yield cli.open();
|
||||||
yield cli.open();
|
yield cli.destroy();
|
||||||
yield cli.destroy();
|
});
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
main().then(process.exit).catch(function(err) {
|
main().then(process.exit).catch(function(err) {
|
||||||
console.error(err.stack + '');
|
console.error(err.stack + '');
|
||||||
|
|||||||
13
bin/spvnode
13
bin/spvnode
@ -25,6 +25,19 @@ node.on('error', function(err) {
|
|||||||
;
|
;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
process.on('uncaughtException', function(err) {
|
||||||
|
node.logger.debug(err.stack);
|
||||||
|
node.logger.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('unhandledRejection', function(err, promise) {
|
||||||
|
node.logger.debug('Unhandled Rejection');
|
||||||
|
node.logger.debug(err.stack);
|
||||||
|
node.logger.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
node.open().then(function() {
|
node.open().then(function() {
|
||||||
if (process.argv.indexOf('--test') !== -1) {
|
if (process.argv.indexOf('--test') !== -1) {
|
||||||
node.pool.watchAddress('1VayNert3x1KzbpzMGt2qdqrAThiRovi8');
|
node.pool.watchAddress('1VayNert3x1KzbpzMGt2qdqrAThiRovi8');
|
||||||
|
|||||||
@ -1185,7 +1185,7 @@ ChainDB.prototype.scan = co(function* scan(start, filter, iter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yield* iter(entry, txs);
|
yield iter(entry, txs);
|
||||||
entry = yield entry.getNext();
|
entry = yield entry.getNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -126,6 +126,7 @@ function Environment() {
|
|||||||
this.require('bloom', './utils/bloom');
|
this.require('bloom', './utils/bloom');
|
||||||
this.require('uri', './utils/uri');
|
this.require('uri', './utils/uri');
|
||||||
this.require('errors', './utils/errors');
|
this.require('errors', './utils/errors');
|
||||||
|
this.require('spawn', './utils/spawn');
|
||||||
|
|
||||||
// Crypto
|
// Crypto
|
||||||
this.require('ec', './crypto/ec');
|
this.require('ec', './crypto/ec');
|
||||||
@ -207,6 +208,7 @@ function Environment() {
|
|||||||
|
|
||||||
// HTTP
|
// HTTP
|
||||||
this.require('http', './http');
|
this.require('http', './http');
|
||||||
|
this.require('rpc', './http/rpc');
|
||||||
|
|
||||||
// Workers
|
// Workers
|
||||||
this.require('workers', './workers/workers');
|
this.require('workers', './workers/workers');
|
||||||
@ -343,6 +345,7 @@ Environment.prototype.cache = function cache() {
|
|||||||
require('./utils/bloom');
|
require('./utils/bloom');
|
||||||
require('./utils/uri');
|
require('./utils/uri');
|
||||||
require('./utils/errors');
|
require('./utils/errors');
|
||||||
|
require('./utils/spawn');
|
||||||
require('./crypto/ec');
|
require('./crypto/ec');
|
||||||
require('./crypto/crypto');
|
require('./crypto/crypto');
|
||||||
require('./crypto/chachapoly');
|
require('./crypto/chachapoly');
|
||||||
@ -399,6 +402,7 @@ Environment.prototype.cache = function cache() {
|
|||||||
require('./wallet/walletdb');
|
require('./wallet/walletdb');
|
||||||
require('./wallet/path');
|
require('./wallet/path');
|
||||||
require('./http');
|
require('./http');
|
||||||
|
require('./http/rpc');
|
||||||
require('./workers/workers');
|
require('./workers/workers');
|
||||||
require('./bip70/bip70');
|
require('./bip70/bip70');
|
||||||
};
|
};
|
||||||
|
|||||||
@ -162,7 +162,7 @@ HTTPBase.prototype._initRouter = function _initRouter() {
|
|||||||
// Avoid stack overflows
|
// Avoid stack overflows
|
||||||
utils.nextTick(function() {
|
utils.nextTick(function() {
|
||||||
try {
|
try {
|
||||||
callback(req, res, next, _send);
|
callback.call(route.ctx, req, res, _send, next);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
done(e);
|
done(e);
|
||||||
}
|
}
|
||||||
@ -264,11 +264,11 @@ HTTPBase.prototype._handle = function _handle(req, res, _send, callback) {
|
|||||||
handler = self.stack[i++];
|
handler = self.stack[i++];
|
||||||
|
|
||||||
utils.nextTick(function() {
|
utils.nextTick(function() {
|
||||||
if (handler.path && req.pathname.indexOf(handler.path) === -1)
|
if (handler.path && req.pathname.indexOf(handler.path) !== 0)
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
handler.callback(req, res, next, _send);
|
handler.callback.call(handler.ctx, req, res, _send, next);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
next(e);
|
next(e);
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ HTTPBase.prototype._handle = function _handle(req, res, _send, callback) {
|
|||||||
* @param {RouteCallback} callback
|
* @param {RouteCallback} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPBase.prototype.use = function use(path, callback) {
|
HTTPBase.prototype.use = function use(path, callback, ctx) {
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
callback = path;
|
callback = path;
|
||||||
path = null;
|
path = null;
|
||||||
@ -299,12 +299,12 @@ HTTPBase.prototype.use = function use(path, callback) {
|
|||||||
|
|
||||||
if (Array.isArray(path)) {
|
if (Array.isArray(path)) {
|
||||||
path.forEach(function(path) {
|
path.forEach(function(path) {
|
||||||
this.use(path, callback);
|
this.use(path, callback, ctx);
|
||||||
}, this);
|
}, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stack.push({ path: path, callback: callback });
|
this.stack.push({ ctx: ctx, path: path, callback: callback });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -313,14 +313,14 @@ HTTPBase.prototype.use = function use(path, callback) {
|
|||||||
* @param {RouteCallback} callback
|
* @param {RouteCallback} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPBase.prototype.get = function get(path, callback) {
|
HTTPBase.prototype.get = function get(path, callback, ctx) {
|
||||||
if (Array.isArray(path)) {
|
if (Array.isArray(path)) {
|
||||||
path.forEach(function(path) {
|
path.forEach(function(path) {
|
||||||
this.get(path, callback);
|
this.get(path, callback, ctx);
|
||||||
}, this);
|
}, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.routes.get.push({ path: path, callback: callback });
|
this.routes.get.push({ ctx: ctx, path: path, callback: callback });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -329,14 +329,14 @@ HTTPBase.prototype.get = function get(path, callback) {
|
|||||||
* @param {RouteCallback} callback
|
* @param {RouteCallback} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPBase.prototype.post = function post(path, callback) {
|
HTTPBase.prototype.post = function post(path, callback, ctx) {
|
||||||
if (Array.isArray(path)) {
|
if (Array.isArray(path)) {
|
||||||
path.forEach(function(path) {
|
path.forEach(function(path) {
|
||||||
this.post(path, callback);
|
this.post(path, callback, ctx);
|
||||||
}, this);
|
}, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.routes.post.push({ path: path, callback: callback });
|
this.routes.post.push({ ctx: ctx, path: path, callback: callback });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,14 +345,14 @@ HTTPBase.prototype.post = function post(path, callback) {
|
|||||||
* @param {RouteCallback} callback
|
* @param {RouteCallback} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPBase.prototype.put = function put(path, callback) {
|
HTTPBase.prototype.put = function put(path, callback, ctx) {
|
||||||
if (Array.isArray(path)) {
|
if (Array.isArray(path)) {
|
||||||
path.forEach(function(path) {
|
path.forEach(function(path) {
|
||||||
this.put(path, callback);
|
this.put(path, callback, ctx);
|
||||||
}, this);
|
}, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.routes.put.push({ path: path, callback: callback });
|
this.routes.put.push({ ctx: ctx, path: path, callback: callback });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -361,14 +361,14 @@ HTTPBase.prototype.put = function put(path, callback) {
|
|||||||
* @param {RouteCallback} callback
|
* @param {RouteCallback} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPBase.prototype.del = function del(path, callback) {
|
HTTPBase.prototype.del = function del(path, callback, ctx) {
|
||||||
if (Array.isArray(path)) {
|
if (Array.isArray(path)) {
|
||||||
path.forEach(function(path) {
|
path.forEach(function(path) {
|
||||||
this.del(path, callback);
|
this.del(path, callback, ctx);
|
||||||
}, this);
|
}, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.routes.del.push({ path: path, callback: callback });
|
this.routes.del.push({ ctx: ctx, path: path, callback: callback });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1393,14 +1393,10 @@ RPC.prototype._getwork = co(function* _getwork() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
RPC.prototype.getworklp = function getworklp(args) {
|
RPC.prototype.getworklp = co(function* getworklp(args) {
|
||||||
var self = this;
|
yield this._onBlock();
|
||||||
return new Promise(function(resolve, reject) {
|
return yield this._getwork();
|
||||||
self.once('clear block', function() {
|
});
|
||||||
self._getwork().then(resolve).catch(reject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
RPC.prototype.getwork = co(function* getwork(args) {
|
RPC.prototype.getwork = co(function* getwork(args) {
|
||||||
var unlock = yield this.locker.lock();
|
var unlock = yield this.locker.lock();
|
||||||
@ -1686,27 +1682,32 @@ RPC.prototype._tmpl = co(function* _tmpl(version, coinbase, rules) {
|
|||||||
return template;
|
return template;
|
||||||
});
|
});
|
||||||
|
|
||||||
RPC.prototype._poll = function _poll(lpid) {
|
RPC.prototype._poll = co(function* _poll(lpid) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var watched, lastTX;
|
var watched, lastTX;
|
||||||
|
|
||||||
if (typeof lpid !== 'string')
|
if (typeof lpid !== 'string')
|
||||||
return Promise.resolve(null);
|
return null;
|
||||||
|
|
||||||
if (lpid.length !== 74)
|
if (lpid.length !== 74)
|
||||||
return Promise.reject(new RPCError('Invalid parameter.'));
|
throw new RPCError('Invalid parameter.');
|
||||||
|
|
||||||
watched = lpid.slice(0, 64);
|
watched = lpid.slice(0, 64);
|
||||||
lastTX = +lpid.slice(64, 74);
|
lastTX = +lpid.slice(64, 74);
|
||||||
|
|
||||||
if (!utils.isHex(watched) || !utils.isNumber(lastTX))
|
if (!utils.isHex(watched) || !utils.isNumber(lastTX))
|
||||||
return Promise.reject(new RPCError('Invalid parameter.'));
|
throw new RPCError('Invalid parameter.');
|
||||||
|
|
||||||
watched = utils.revHex(watched);
|
watched = utils.revHex(watched);
|
||||||
|
|
||||||
if (this.chain.tip.hash !== watched)
|
if (this.chain.tip.hash !== watched)
|
||||||
return Promise.resolve(null);
|
return null;
|
||||||
|
|
||||||
|
yield this._onBlock();
|
||||||
|
});
|
||||||
|
|
||||||
|
RPC.prototype._onBlock = function _onBlock() {
|
||||||
|
var self = this;
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
self.once('clear block', resolve);
|
self.once('clear block', resolve);
|
||||||
});
|
});
|
||||||
@ -1855,42 +1856,39 @@ RPC.prototype.prioritisetransaction = function prioritisetransaction(args) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
RPC.prototype._hashps = co(function* _hashps(lookup, height) {
|
RPC.prototype._hashps = co(function* _hashps(lookup, height) {
|
||||||
var i, minTime, maxTime, pb0, time;
|
var i, minTime, maxTime, workDiff, timeDiff, ps, tip, entry;
|
||||||
var workDiff, timeDiff, ps, pb, entry;
|
|
||||||
|
|
||||||
pb = this.chain.tip;
|
tip = this.chain.tip;
|
||||||
if (height >= 0 && height < this.chain.tip.height)
|
if (height >= 0 && height < this.chain.tip.height)
|
||||||
pb = yield this.chain.db.get(height);
|
tip = yield this.chain.db.get(height);
|
||||||
|
|
||||||
if (!pb)
|
if (!tip)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lookup <= 0)
|
if (lookup <= 0)
|
||||||
lookup = pb.height % this.network.pow.retargetInterval + 1;
|
lookup = tip.height % this.network.pow.retargetInterval + 1;
|
||||||
|
|
||||||
if (lookup > pb.height)
|
if (lookup > tip.height)
|
||||||
lookup = pb.height;
|
lookup = tip.height;
|
||||||
|
|
||||||
minTime = pb.ts;
|
minTime = tip.ts;
|
||||||
maxTime = minTime;
|
maxTime = minTime;
|
||||||
pb0 = pb;
|
entry = tip;
|
||||||
|
|
||||||
for (i = 0; i < lookup; i++) {
|
for (i = 0; i < lookup; i++) {
|
||||||
entry = yield pb0.getPrevious();
|
entry = yield entry.getPrevious();
|
||||||
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
throw new RPCError('Not found.');
|
throw new RPCError('Not found.');
|
||||||
|
|
||||||
pb0 = entry;
|
minTime = Math.min(entry.ts, minTime);
|
||||||
time = pb0.ts;
|
maxTime = Math.max(entry.ts, maxTime);
|
||||||
minTime = Math.min(time, minTime);
|
|
||||||
maxTime = Math.max(time, maxTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minTime === maxTime)
|
if (minTime === maxTime)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
workDiff = pb.chainwork.sub(pb0.chainwork);
|
workDiff = tip.chainwork.sub(entry.chainwork);
|
||||||
timeDiff = maxTime - minTime;
|
timeDiff = maxTime - minTime;
|
||||||
ps = +workDiff.toString(10) / timeDiff;
|
ps = +workDiff.toString(10) / timeDiff;
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ var HTTPBase = http.base;
|
|||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var spawn = require('../utils/spawn');
|
var spawn = require('../utils/spawn');
|
||||||
var co = spawn.co;
|
var co = spawn.co;
|
||||||
|
var con = spawn.con;
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var RPC; /*= require('./rpc'); - load lazily */
|
var RPC; /*= require('./rpc'); - load lazily */
|
||||||
@ -101,7 +102,7 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
address.address, address.port);
|
address.address, address.port);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.use(function(req, res, next, send) {
|
this.use(function(req, res, send, next) {
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
||||||
res.setHeader(
|
res.setHeader(
|
||||||
@ -115,14 +116,14 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
|
|
||||||
res.setHeader('X-Bcoin-Version', constants.USER_VERSION);
|
res.setHeader('X-Bcoin-Version', constants.USER_VERSION);
|
||||||
res.setHeader('X-Bcoin-Agent', constants.USER_AGENT);
|
res.setHeader('X-Bcoin-Agent', constants.USER_AGENT);
|
||||||
res.setHeader('X-Bcoin-Network', self.network.type);
|
res.setHeader('X-Bcoin-Network', this.network.type);
|
||||||
res.setHeader('X-Bcoin-Height', self.chain.height + '');
|
res.setHeader('X-Bcoin-Height', this.chain.height + '');
|
||||||
res.setHeader('X-Bcoin-Tip', utils.revHex(self.chain.tip.hash));
|
res.setHeader('X-Bcoin-Tip', utils.revHex(this.chain.tip.hash));
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.use(function(req, res, next, send) {
|
this.use(function(req, res, send, next) {
|
||||||
var auth = req.headers['authorization'];
|
var auth = req.headers['authorization'];
|
||||||
var parts;
|
var parts;
|
||||||
|
|
||||||
@ -145,11 +146,11 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.use(function(req, res, next, send) {
|
this.use(function(req, res, send, next) {
|
||||||
if (!self.apiHash)
|
if (!this.apiHash)
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
if (crypto.ccmp(hash256(req.password), self.apiHash))
|
if (crypto.ccmp(hash256(req.password), this.apiHash))
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
res.setHeader('WWW-Authenticate', 'Basic realm="node"');
|
res.setHeader('WWW-Authenticate', 'Basic realm="node"');
|
||||||
@ -170,7 +171,7 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
send(401, { error: 'Bad API key.' });
|
send(401, { error: 'Bad API key.' });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.use(function(req, res, next, send) {
|
this.use(function(req, res, send, next) {
|
||||||
var i, params, options, output, address;
|
var i, params, options, output, address;
|
||||||
|
|
||||||
if (req.method === 'POST' && req.pathname === '/') {
|
if (req.method === 'POST' && req.pathname === '/') {
|
||||||
@ -187,8 +188,8 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
softMerge(params, req.query, true);
|
softMerge(params, req.query, true);
|
||||||
softMerge(params, req.body);
|
softMerge(params, req.body);
|
||||||
|
|
||||||
self.logger.debug('Params:');
|
this.logger.debug('Params:');
|
||||||
self.logger.debug(params);
|
this.logger.debug(params);
|
||||||
|
|
||||||
if (params.id) {
|
if (params.id) {
|
||||||
assert(typeof params.id === 'string', 'ID must be a string.');
|
assert(typeof params.id === 'string', 'ID must be a string.');
|
||||||
@ -374,37 +375,16 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.use(function(req, res, next, send) {
|
this.use(con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var wallet;
|
||||||
var wallet;
|
|
||||||
|
|
||||||
if (req.path.length < 2 || req.path[0] !== 'wallet') {
|
if (req.path.length < 2 || req.path[0] !== 'wallet') {
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.options.walletAuth) {
|
if (!this.options.walletAuth) {
|
||||||
wallet = yield self.walletdb.get(req.options.id);
|
wallet = yield this.walletdb.get(req.options.id);
|
||||||
|
|
||||||
if (!wallet) {
|
|
||||||
send(404);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
req.wallet = wallet;
|
|
||||||
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
wallet = yield self.walletdb.auth(req.options.id, req.options.token);
|
|
||||||
} catch (err) {
|
|
||||||
self.logger.info('Auth failure for %s: %s.',
|
|
||||||
req.options.id, err.message);
|
|
||||||
send(403, { error: err.message });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wallet) {
|
if (!wallet) {
|
||||||
send(404);
|
send(404);
|
||||||
@ -412,458 +392,411 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.wallet = wallet;
|
req.wallet = wallet;
|
||||||
self.logger.info('Successful auth for %s.', req.options.id);
|
|
||||||
next();
|
next();
|
||||||
}).catch(next);
|
return;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
wallet = yield this.walletdb.auth(req.options.id, req.options.token);
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.info('Auth failure for %s: %s.',
|
||||||
|
req.options.id, err.message);
|
||||||
|
send(403, { error: err.message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wallet) {
|
||||||
|
send(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.wallet = wallet;
|
||||||
|
this.logger.info('Successful auth for %s.', req.options.id);
|
||||||
|
next();
|
||||||
|
}));
|
||||||
|
|
||||||
// JSON RPC
|
// JSON RPC
|
||||||
this.post('/', function(req, res, next, send) {
|
this.post('/', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var json;
|
||||||
var json;
|
|
||||||
|
|
||||||
if (!self.rpc) {
|
if (!this.rpc) {
|
||||||
RPC = require('./rpc');
|
RPC = require('./rpc');
|
||||||
self.rpc = new RPC(self.node);
|
this.rpc = new RPC(this.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.body.method === 'getwork') {
|
if (req.body.method === 'getwork') {
|
||||||
res.setHeader('X-Long-Polling', '/?longpoll=1');
|
res.setHeader('X-Long-Polling', '/?longpoll=1');
|
||||||
if (req.query.longpoll)
|
if (req.query.longpoll)
|
||||||
req.body.method = 'getworklp';
|
req.body.method = 'getworklp';
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
json = yield self.rpc.execute(req.body);
|
json = yield this.rpc.execute(req.body);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
self.logger.error(err);
|
this.logger.error(err);
|
||||||
|
|
||||||
if (err.type === 'RPCError') {
|
if (err.type === 'RPCError') {
|
||||||
return send(400, {
|
return send(400, {
|
||||||
result: err.message,
|
result: err.message,
|
||||||
error: null,
|
error: null,
|
||||||
id: req.body.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return send(500, {
|
|
||||||
result: null,
|
|
||||||
error: {
|
|
||||||
message: err.message,
|
|
||||||
code: 1
|
|
||||||
},
|
|
||||||
id: req.body.id
|
id: req.body.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
send(200, {
|
return send(500, {
|
||||||
result: json != null ? json : null,
|
result: null,
|
||||||
error: null,
|
error: {
|
||||||
|
message: err.message,
|
||||||
|
code: 1
|
||||||
|
},
|
||||||
id: req.body.id
|
id: req.body.id
|
||||||
});
|
});
|
||||||
}).catch(next);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
this.get('/', function(req, res, next, send) {
|
send(200, {
|
||||||
|
result: json != null ? json : null,
|
||||||
|
error: null,
|
||||||
|
id: req.body.id
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.get('/', function(req, res, send, next) {
|
||||||
send(200, {
|
send(200, {
|
||||||
version: constants.USER_VERSION,
|
version: constants.USER_VERSION,
|
||||||
agent: constants.USER_AGENT,
|
agent: constants.USER_AGENT,
|
||||||
services: self.pool.services,
|
services: this.pool.services,
|
||||||
network: self.network.type,
|
network: this.network.type,
|
||||||
height: self.chain.height,
|
height: this.chain.height,
|
||||||
tip: self.chain.tip.rhash,
|
tip: this.chain.tip.rhash,
|
||||||
peers: self.pool.peers.all.length,
|
peers: this.pool.peers.all.length,
|
||||||
progress: self.chain.getProgress()
|
progress: this.chain.getProgress()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// UTXO by address
|
// UTXO by address
|
||||||
this.get('/coin/address/:address', function(req, res, next, send) {
|
this.get('/coin/address/:address', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var coins = yield this.node.getCoinsByAddress(req.options.address);
|
||||||
var coins = yield self.node.getCoinsByAddress(req.options.address);
|
send(200, coins.map(function(coin) {
|
||||||
send(200, coins.map(function(coin) {
|
return coin.toJSON();
|
||||||
return coin.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// UTXO by id
|
// UTXO by id
|
||||||
this.get('/coin/:hash/:index', function(req, res, next, send) {
|
this.get('/coin/:hash/:index', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var coin = yield this.node.getCoin(req.options.hash, req.options.index);
|
||||||
var coin = yield self.node.getCoin(req.options.hash, req.options.index);
|
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
send(200, coin.toJSON());
|
send(200, coin.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Bulk read UTXOs
|
// Bulk read UTXOs
|
||||||
this.post('/coin/address', function(req, res, next, send) {
|
this.post('/coin/address', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var coins = yield this.node.getCoinsByAddress(req.options.address);
|
||||||
var coins = yield self.node.getCoinsByAddress(req.options.address);
|
send(200, coins.map(function(coin) {
|
||||||
send(200, coins.map(function(coin) {
|
return coin.toJSON();
|
||||||
return coin.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// TX by hash
|
// TX by hash
|
||||||
this.get('/tx/:hash', function(req, res, next, send) {
|
this.get('/tx/:hash', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var tx = yield this.node.getTX(req.options.hash);
|
||||||
var tx = yield self.node.getTX(req.options.hash);
|
|
||||||
|
|
||||||
if (!tx)
|
if (!tx)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
yield self.node.fillHistory(tx);
|
yield this.node.fillHistory(tx);
|
||||||
|
|
||||||
send(200, tx.toJSON());
|
send(200, tx.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// TX by address
|
// TX by address
|
||||||
this.get('/tx/address/:address', function(req, res, next, send) {
|
this.get('/tx/address/:address', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var txs = yield this.node.getTXByAddress(req.options.address);
|
||||||
var txs = yield self.node.getTXByAddress(req.options.address);
|
var i, tx;
|
||||||
var i, tx;
|
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++) {
|
for (i = 0; i < txs.length; i++) {
|
||||||
tx = txs[i];
|
tx = txs[i];
|
||||||
yield self.node.fillHistory(tx);
|
yield this.node.fillHistory(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
send(200, txs.map(function(tx) {
|
send(200, txs.map(function(tx) {
|
||||||
return tx.toJSON();
|
return tx.toJSON();
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Bulk read TXs
|
// Bulk read TXs
|
||||||
this.post('/tx/address', function(req, res, next, send) {
|
this.post('/tx/address', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var txs = yield this.node.getTXByAddress(req.options.address);
|
||||||
var txs = yield self.node.getTXByAddress(req.options.address);
|
var i, tx;
|
||||||
var i, tx;
|
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++) {
|
for (i = 0; i < txs.length; i++) {
|
||||||
tx = txs[i];
|
tx = txs[i];
|
||||||
yield self.node.fillHistory(tx);
|
yield this.node.fillHistory(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
send(200, txs.map(function(tx) {
|
send(200, txs.map(function(tx) {
|
||||||
return tx.toJSON();
|
return tx.toJSON();
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Block by hash/height
|
// Block by hash/height
|
||||||
this.get('/block/:hash', function(req, res, next, send) {
|
this.get('/block/:hash', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var hash = req.options.hash || req.options.height;
|
||||||
var hash = req.options.hash || req.options.height;
|
var block = yield this.node.getFullBlock(hash);
|
||||||
var block = yield self.node.getFullBlock(hash);
|
|
||||||
|
|
||||||
if (!block)
|
if (!block)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
send(200, block.toJSON());
|
send(200, block.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Mempool snapshot
|
// Mempool snapshot
|
||||||
this.get('/mempool', function(req, res, next, send) {
|
this.get('/mempool', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var i, txs, tx;
|
||||||
var i, txs, tx;
|
|
||||||
|
|
||||||
if (!self.mempool)
|
if (!this.mempool)
|
||||||
return send(400, { error: 'No mempool available.' });
|
return send(400, { error: 'No mempool available.' });
|
||||||
|
|
||||||
txs = self.mempool.getHistory();
|
txs = this.mempool.getHistory();
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++) {
|
for (i = 0; i < txs.length; i++) {
|
||||||
tx = txs[i];
|
tx = txs[i];
|
||||||
yield self.node.fillHistory(tx);
|
yield this.node.fillHistory(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
send(200, txs.map(function(tx) {
|
send(200, txs.map(function(tx) {
|
||||||
return tx.toJSON();
|
return tx.toJSON();
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Broadcast TX
|
// Broadcast TX
|
||||||
this.post('/broadcast', function(req, res, next, send) {
|
this.post('/broadcast', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
yield this.node.sendTX(req.options.tx);
|
||||||
yield self.node.sendTX(req.options.tx);
|
send(200, { success: true });
|
||||||
send(200, { success: true });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Estimate fee
|
// Estimate fee
|
||||||
this.get('/fee', function(req, res, next, send) {
|
this.get('/fee', function(req, res, send, next) {
|
||||||
var fee;
|
var fee;
|
||||||
|
|
||||||
if (!self.fees)
|
if (!this.fees)
|
||||||
return send(400, { error: 'Fee estimation not available.' });
|
return send(400, { error: 'Fee estimation not available.' });
|
||||||
|
|
||||||
fee = self.fees.estimateFee(req.options.blocks);
|
fee = this.fees.estimateFee(req.options.blocks);
|
||||||
|
|
||||||
send(200, { rate: utils.btc(fee) });
|
send(200, { rate: utils.btc(fee) });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get wallet
|
// Get wallet
|
||||||
this.get('/wallet/:id', function(req, res, next, send) {
|
this.get('/wallet/:id', function(req, res, send, next) {
|
||||||
send(200, req.wallet.toJSON());
|
send(200, req.wallet.toJSON());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create wallet
|
// Create wallet
|
||||||
this.post('/wallet/:id?', function(req, res, next, send) {
|
this.post('/wallet/:id?', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var wallet = yield this.walletdb.create(req.options);
|
||||||
var wallet = yield self.walletdb.create(req.options);
|
send(200, wallet.toJSON());
|
||||||
send(200, wallet.toJSON());
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// List accounts
|
// List accounts
|
||||||
this.get('/wallet/:id/account', function(req, res, next, send) {
|
this.get('/wallet/:id/account', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var accounts = yield req.wallet.getAccounts();
|
||||||
var accounts = yield req.wallet.getAccounts();
|
send(200, accounts);
|
||||||
send(200, accounts);
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get account
|
// Get account
|
||||||
this.get('/wallet/:id/account/:account', function(req, res, next, send) {
|
this.get('/wallet/:id/account/:account', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = yield req.wallet.getAccount(req.options.account);
|
||||||
var account = yield req.wallet.getAccount(req.options.account);
|
|
||||||
|
|
||||||
if (!account)
|
if (!account)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
send(200, account.toJSON());
|
send(200, account.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Create/get account
|
// Create/get account
|
||||||
this.post('/wallet/:id/account/:account?', function(req, res, next, send) {
|
this.post('/wallet/:id/account/:account?', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = yield req.wallet.createAccount(req.options);
|
||||||
var account = yield req.wallet.createAccount(req.options);
|
|
||||||
|
|
||||||
if (!account)
|
if (!account)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
send(200, account.toJSON());
|
send(200, account.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Change passphrase
|
// Change passphrase
|
||||||
this.post('/wallet/:id/passphrase', function(req, res, next, send) {
|
this.post('/wallet/:id/passphrase', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var options = req.options;
|
||||||
var options = req.options;
|
var old = options.old;
|
||||||
var old = options.old;
|
var new_ = options.passphrase;
|
||||||
var new_ = options.passphrase;
|
yield req.wallet.setPassphrase(old, new_);
|
||||||
yield req.wallet.setPassphrase(old, new_);
|
send(200, { success: true });
|
||||||
send(200, { success: true });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate new token
|
// Generate new token
|
||||||
this.post('/wallet/:id/retoken', function(req, res, next, send) {
|
this.post('/wallet/:id/retoken', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var options = req.options;
|
||||||
var options = req.options;
|
var token = yield req.wallet.retoken(options.passphrase);
|
||||||
var token = yield req.wallet.retoken(options.passphrase);
|
send(200, { token: token.toString('hex') });
|
||||||
send(200, { token: token.toString('hex') });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send TX
|
// Send TX
|
||||||
this.post('/wallet/:id/send', function(req, res, next, send) {
|
this.post('/wallet/:id/send', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var options = req.options;
|
||||||
var options = req.options;
|
var tx = yield req.wallet.send(options);
|
||||||
var tx = yield req.wallet.send(options);
|
send(200, tx.toJSON());
|
||||||
send(200, tx.toJSON());
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create TX
|
// Create TX
|
||||||
this.post('/wallet/:id/create', function(req, res, next, send) {
|
this.post('/wallet/:id/create', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var options = req.options;
|
||||||
var options = req.options;
|
var tx = yield req.wallet.createTX(options);
|
||||||
var tx = yield req.wallet.createTX(options);
|
yield req.wallet.sign(tx, options);
|
||||||
yield req.wallet.sign(tx, options);
|
send(200, tx.toJSON());
|
||||||
send(200, tx.toJSON());
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sign TX
|
// Sign TX
|
||||||
this.post('/wallet/:id/sign', function(req, res, next, send) {
|
this.post('/wallet/:id/sign', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var options = req.options;
|
||||||
var options = req.options;
|
var tx = req.options.tx;
|
||||||
var tx = req.options.tx;
|
yield req.wallet.sign(tx, options);
|
||||||
yield req.wallet.sign(tx, options);
|
send(200, tx.toJSON());
|
||||||
send(200, tx.toJSON());
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fill TX
|
// Fill TX
|
||||||
this.post('/wallet/:id/fill', function(req, res, next, send) {
|
this.post('/wallet/:id/fill', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var tx = req.options.tx;
|
||||||
var tx = req.options.tx;
|
yield req.wallet.fillHistory(tx);
|
||||||
yield req.wallet.fillHistory(tx);
|
send(200, tx.toJSON());
|
||||||
send(200, tx.toJSON());
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Zap Wallet TXs
|
// Zap Wallet TXs
|
||||||
this.post('/wallet/:id/zap', function(req, res, next, send) {
|
this.post('/wallet/:id/zap', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var age = req.options.age;
|
||||||
var age = req.options.age;
|
yield req.wallet.zap(account, age);
|
||||||
yield req.wallet.zap(account, age);
|
send(200, { success: true });
|
||||||
send(200, { success: true });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Abandon Wallet TX
|
// Abandon Wallet TX
|
||||||
this.del('/wallet/:id/tx/:hash', function(req, res, next, send) {
|
this.del('/wallet/:id/tx/:hash', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var hash = req.options.hash;
|
||||||
var hash = req.options.hash;
|
yield req.wallet.abandon(hash);
|
||||||
yield req.wallet.abandon(hash);
|
send(200, { success: true });
|
||||||
send(200, { success: true });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add key
|
// Add key
|
||||||
this.put('/wallet/:id/key', function(req, res, next, send) {
|
this.put('/wallet/:id/key', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var key = req.options.key;
|
||||||
var key = req.options.key;
|
yield req.wallet.addKey(account, key);
|
||||||
yield req.wallet.addKey(account, key);
|
send(200, { success: true });
|
||||||
send(200, { success: true });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove key
|
// Remove key
|
||||||
this.del('/wallet/:id/key', function(req, res, next, send) {
|
this.del('/wallet/:id/key', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var key = req.options.key;
|
||||||
var key = req.options.key;
|
yield req.wallet.removeKey(account, key);
|
||||||
yield req.wallet.removeKey(account, key);
|
send(200, { success: true });
|
||||||
send(200, { success: true });
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create address
|
// Create address
|
||||||
this.post('/wallet/:id/address', function(req, res, next, send) {
|
this.post('/wallet/:id/address', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var address = yield req.wallet.createReceive(account);
|
||||||
var address = yield req.wallet.createReceive(account);
|
send(200, address.toJSON());
|
||||||
send(200, address.toJSON());
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet Balance
|
// Wallet Balance
|
||||||
this.get('/wallet/:id/balance', function(req, res, next, send) {
|
this.get('/wallet/:id/balance', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var balance = yield req.wallet.getBalance(account);
|
||||||
var balance = yield req.wallet.getBalance(account);
|
|
||||||
|
|
||||||
if (!balance)
|
if (!balance)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
send(200, balance.toJSON());
|
send(200, balance.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet UTXOs
|
// Wallet UTXOs
|
||||||
this.get('/wallet/:id/coin', function(req, res, next, send) {
|
this.get('/wallet/:id/coin', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var coins = yield req.wallet.getCoins(account);
|
||||||
var coins = yield req.wallet.getCoins(account);
|
send(200, coins.map(function(coin) {
|
||||||
send(200, coins.map(function(coin) {
|
return coin.toJSON();
|
||||||
return coin.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet Coin
|
// Wallet Coin
|
||||||
this.get('/wallet/:id/coin/:hash/:index', function(req, res, next, send) {
|
this.get('/wallet/:id/coin/:hash/:index', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var hash = req.options.hash;
|
||||||
var hash = req.options.hash;
|
var index = req.options.index;
|
||||||
var index = req.options.index;
|
var coin = yield req.wallet.getCoin(hash, index);
|
||||||
var coin = yield req.wallet.getCoin(hash, index);
|
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
send(200, coin.toJSON());
|
send(200, coin.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet TXs
|
// Wallet TXs
|
||||||
this.get('/wallet/:id/tx/history', function(req, res, next, send) {
|
this.get('/wallet/:id/tx/history', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var txs = yield req.wallet.getHistory(account);
|
||||||
var txs = yield req.wallet.getHistory(account);
|
var details = yield req.wallet.toDetails(txs);
|
||||||
var details = yield req.wallet.toDetails(txs);
|
send(200, details.map(function(tx) {
|
||||||
send(200, details.map(function(tx) {
|
return tx.toJSON();
|
||||||
return tx.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet Pending TXs
|
// Wallet Pending TXs
|
||||||
this.get('/wallet/:id/tx/unconfirmed', function(req, res, next, send) {
|
this.get('/wallet/:id/tx/unconfirmed', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var txs = yield req.wallet.getUnconfirmed(account);
|
||||||
var txs = yield req.wallet.getUnconfirmed(account);
|
var details = yield req.wallet.toDetails(txs);
|
||||||
var details = yield req.wallet.toDetails(txs);
|
send(200, details.map(function(tx) {
|
||||||
send(200, details.map(function(tx) {
|
return tx.toJSON();
|
||||||
return tx.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet TXs within time range
|
// Wallet TXs within time range
|
||||||
this.get('/wallet/:id/tx/range', function(req, res, next, send) {
|
this.get('/wallet/:id/tx/range', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var options = req.options;
|
||||||
var options = req.options;
|
var txs = yield req.wallet.getRange(account, options);
|
||||||
var txs = yield req.wallet.getRange(account, options);
|
var details = yield req.wallet.toDetails(txs);
|
||||||
var details = yield req.wallet.toDetails(txs);
|
send(200, details.map(function(tx) {
|
||||||
send(200, details.map(function(tx) {
|
return tx.toJSON();
|
||||||
return tx.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Last Wallet TXs
|
// Last Wallet TXs
|
||||||
this.get('/wallet/:id/tx/last', function(req, res, next, send) {
|
this.get('/wallet/:id/tx/last', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var account = req.options.account;
|
||||||
var account = req.options.account;
|
var limit = req.options.limit;
|
||||||
var limit = req.options.limit;
|
var txs = yield req.wallet.getLast(account, limit);
|
||||||
var txs = yield req.wallet.getLast(account, limit);
|
var details = yield req.wallet.toDetails(txs);
|
||||||
var details = yield req.wallet.toDetails(txs);
|
send(200, details.map(function(tx) {
|
||||||
send(200, details.map(function(tx) {
|
return tx.toJSON();
|
||||||
return tx.toJSON();
|
}));
|
||||||
}));
|
}));
|
||||||
}).catch(next);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wallet TX
|
// Wallet TX
|
||||||
this.get('/wallet/:id/tx/:hash', function(req, res, next, send) {
|
this.get('/wallet/:id/tx/:hash', con(function *(req, res, send, next) {
|
||||||
spawn(function *() {
|
var hash = req.options.hash;
|
||||||
var hash = req.options.hash;
|
var tx = yield req.wallet.getTX(hash);
|
||||||
var tx = yield req.wallet.getTX(hash);
|
var details;
|
||||||
var details;
|
|
||||||
|
|
||||||
if (!tx)
|
if (!tx)
|
||||||
return send(404);
|
return send(404);
|
||||||
|
|
||||||
details = yield req.wallet.toDetails(tx);
|
details = yield req.wallet.toDetails(tx);
|
||||||
send(200, details.toJSON());
|
send(200, details.toJSON());
|
||||||
}).catch(next);
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
this.server.on('error', function(err) {
|
this.server.on('error', function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
@ -1090,7 +1023,7 @@ HTTPServer.prototype.close = function close() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPServer.prototype.use = function use(path, callback) {
|
HTTPServer.prototype.use = function use(path, callback) {
|
||||||
return this.server.use(path, callback);
|
return this.server.use(path, callback, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1098,7 +1031,7 @@ HTTPServer.prototype.use = function use(path, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPServer.prototype.get = function get(path, callback) {
|
HTTPServer.prototype.get = function get(path, callback) {
|
||||||
return this.server.get(path, callback);
|
return this.server.get(path, callback, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1106,7 +1039,7 @@ HTTPServer.prototype.get = function get(path, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPServer.prototype.post = function post(path, callback) {
|
HTTPServer.prototype.post = function post(path, callback) {
|
||||||
return this.server.post(path, callback);
|
return this.server.post(path, callback, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1114,7 +1047,7 @@ HTTPServer.prototype.post = function post(path, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPServer.prototype.put = function put(path, callback) {
|
HTTPServer.prototype.put = function put(path, callback) {
|
||||||
return this.server.put(path, callback);
|
return this.server.put(path, callback, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1122,7 +1055,7 @@ HTTPServer.prototype.put = function put(path, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HTTPServer.prototype.del = function del(path, callback) {
|
HTTPServer.prototype.del = function del(path, callback) {
|
||||||
return this.server.del(path, callback);
|
return this.server.del(path, callback, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1337,14 +1270,14 @@ ClientSocket.prototype.scan = function scan(start) {
|
|||||||
if (this.chain.db.options.prune)
|
if (this.chain.db.options.prune)
|
||||||
return Promise.reject(new Error('Cannot scan in pruned mode.'));
|
return Promise.reject(new Error('Cannot scan in pruned mode.'));
|
||||||
|
|
||||||
return this.chain.db.scan(start, this.filter, function *(entry, txs) {
|
return this.chain.db.scan(start, this.filter, co(function *(entry, txs) {
|
||||||
for (i = 0; i < txs.length; i++)
|
for (i = 0; i < txs.length; i++)
|
||||||
txs[i] = txs[i].toJSON();
|
txs[i] = txs[i].toJSON();
|
||||||
|
|
||||||
self.emit('block tx', entry.toJSON(), txs);
|
self.emit('block tx', entry.toJSON(), txs);
|
||||||
|
|
||||||
yield utils.wait();
|
yield utils.wait();
|
||||||
});
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
ClientSocket.prototype.join = function join(id) {
|
ClientSocket.prototype.join = function join(id) {
|
||||||
|
|||||||
@ -253,36 +253,36 @@ Miner.prototype.createBlock = co(function* createBlock(tip) {
|
|||||||
// Find target
|
// Find target
|
||||||
target = yield this.chain.getTargetAsync(ts, tip);
|
target = yield this.chain.getTargetAsync(ts, tip);
|
||||||
|
|
||||||
if (this.version != null) {
|
if (this.version != null) {
|
||||||
version = this.version;
|
version = this.version;
|
||||||
} else {
|
} else {
|
||||||
// Calculate version with versionbits
|
// Calculate version with versionbits
|
||||||
version = yield this.chain.computeBlockVersion(tip);
|
version = yield this.chain.computeBlockVersion(tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
attempt = new MinerBlock({
|
attempt = new MinerBlock({
|
||||||
workerPool: this.workerPool,
|
workerPool: this.workerPool,
|
||||||
tip: tip,
|
tip: tip,
|
||||||
version: version,
|
version: version,
|
||||||
target: target,
|
target: target,
|
||||||
address: this.address,
|
address: this.address,
|
||||||
coinbaseFlags: this.coinbaseFlags,
|
coinbaseFlags: this.coinbaseFlags,
|
||||||
witness: this.chain.segwitActive,
|
witness: this.chain.segwitActive,
|
||||||
parallel: this.options.parallel,
|
parallel: this.options.parallel,
|
||||||
network: this.network
|
network: this.network
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!this.mempool)
|
if (!this.mempool)
|
||||||
return attempt;
|
return attempt;
|
||||||
|
|
||||||
txs = this.mempool.getHistory();
|
txs = this.mempool.getHistory();
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++) {
|
for (i = 0; i < txs.length; i++) {
|
||||||
tx = txs[i];
|
tx = txs[i];
|
||||||
attempt.addTX(tx);
|
attempt.addTX(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return attempt;
|
return attempt;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -292,8 +292,8 @@ Miner.prototype.createBlock = co(function* createBlock(tip) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Miner.prototype.mineBlock = co(function* mineBlock(tip) {
|
Miner.prototype.mineBlock = co(function* mineBlock(tip) {
|
||||||
// Create a new block and start hashing
|
// Create a new block and start hashing
|
||||||
var attempt = yield this.createBlock(tip);
|
var attempt = yield this.createBlock(tip);
|
||||||
return yield attempt.mineAsync();
|
return yield attempt.mineAsync();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -102,7 +102,47 @@ function cob(generator) {
|
|||||||
|
|
||||||
gen = generator.apply(this, args);
|
gen = generator.apply(this, args);
|
||||||
|
|
||||||
return cb(exec(gen), callback);
|
return cb(exec(gen), function(err, result) {
|
||||||
|
// Escape the promise's scope:
|
||||||
|
utils.nextTick(function() {
|
||||||
|
callback(err, result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a generator function to be
|
||||||
|
* executed into a function that
|
||||||
|
* accepts a node.js style callback.
|
||||||
|
* Only executes callback on error.
|
||||||
|
* @param {GeneratorFunction}
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function con(generator) {
|
||||||
|
return function() {
|
||||||
|
var i, args, callback, gen;
|
||||||
|
|
||||||
|
if (arguments.length === 0
|
||||||
|
|| typeof arguments[arguments.length - 1] !== 'function') {
|
||||||
|
throw new Error('Function must accept a callback.');
|
||||||
|
}
|
||||||
|
|
||||||
|
args = new Array(arguments.length);
|
||||||
|
callback = arguments[arguments.length - 1];
|
||||||
|
|
||||||
|
for (i = 0; i < args.length; i++)
|
||||||
|
args[i] = arguments[i];
|
||||||
|
|
||||||
|
gen = generator.apply(this, args);
|
||||||
|
|
||||||
|
return exec(gen).catch(function(err) {
|
||||||
|
// Escape the promise's scope:
|
||||||
|
utils.nextTick(function() {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +263,7 @@ exports.exec = exec;
|
|||||||
exports.spawn = spawn;
|
exports.spawn = spawn;
|
||||||
exports.co = co;
|
exports.co = co;
|
||||||
exports.cob = cob;
|
exports.cob = cob;
|
||||||
|
exports.con = con;
|
||||||
exports.cb = cb;
|
exports.cb = cb;
|
||||||
exports.wait = wait;
|
exports.wait = wait;
|
||||||
exports.timeout = timeout;
|
exports.timeout = timeout;
|
||||||
|
|||||||
@ -975,9 +975,9 @@ WalletDB.prototype.rescan = co(function* rescan(chaindb, height) {
|
|||||||
this.logger.info('Scanning for %d addresses.', hashes.length);
|
this.logger.info('Scanning for %d addresses.', hashes.length);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
yield chaindb.scan(height, hashes, function *(block, txs) {
|
yield chaindb.scan(height, hashes, co(function *(block, txs) {
|
||||||
yield self.addBlock(block, txs, true);
|
yield self.addBlock(block, txs, true);
|
||||||
});
|
}));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
unlock();
|
unlock();
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ var crypto = require('../lib/crypto/crypto');
|
|||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var opcodes = constants.opcodes;
|
var opcodes = constants.opcodes;
|
||||||
var spawn = require('../lib/utils/spawn');
|
var spawn = require('../lib/utils/spawn');
|
||||||
|
var co = require('../lib/utils/spawn').co;
|
||||||
var c = require('../lib/utils/spawn').cb;
|
var c = require('../lib/utils/spawn').cb;
|
||||||
|
|
||||||
describe('Chain', function() {
|
describe('Chain', function() {
|
||||||
@ -234,10 +235,10 @@ describe('Chain', function() {
|
|||||||
var total = 0;
|
var total = 0;
|
||||||
c(walletdb.getAddressHashes(), function(err, hashes) {
|
c(walletdb.getAddressHashes(), function(err, hashes) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
c(chain.db.scan(null, hashes, function *(block, txs) {
|
c(chain.db.scan(null, hashes, co(function *(block, txs) {
|
||||||
total += txs.length;
|
total += txs.length;
|
||||||
yield spawn.wait();
|
yield spawn.wait();
|
||||||
}), function(err) {
|
})), function(err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.equal(total, 25);
|
assert.equal(total, 25);
|
||||||
cb();
|
cb();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user