bitcore-wallet-service/lib/expressapp.js

364 lines
9.8 KiB
JavaScript
Raw Normal View History

2015-02-19 06:00:14 -08:00
'use strict';
var _ = require('lodash');
var async = require('async');
var log = require('npmlog');
2015-04-18 02:55:24 -07:00
2015-02-19 06:00:14 -08:00
var express = require('express');
var querystring = require('querystring');
var bodyParser = require('body-parser')
2015-02-20 12:32:19 -08:00
var WalletService = require('./server');
2015-05-26 10:59:55 -07:00
var Stats = require('./stats');
2015-02-19 06:00:14 -08:00
2015-04-18 02:55:24 -07:00
log.disableColor();
2015-02-19 06:00:14 -08:00
log.debug = log.verbose;
log.level = 'debug';
2015-05-07 12:45:17 -07:00
var ExpressApp = function() {
this.app = express();
};
2015-02-19 06:00:14 -08:00
2015-02-21 22:46:47 -08:00
/**
* start
*
* @param opts.WalletService options for WalletService class
* @param opts.basePath
* @param opts.disableLogs
2015-04-21 10:43:35 -07:00
* @param {Callback} cb
2015-02-21 22:46:47 -08:00
*/
2015-05-07 12:45:17 -07:00
ExpressApp.prototype.start = function(opts, cb) {
2015-02-19 06:00:14 -08:00
opts = opts || {};
2015-05-07 12:45:17 -07:00
this.app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
2015-02-19 06:00:14 -08:00
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
2015-03-06 15:11:28 -08:00
res.setHeader('Access-Control-Allow-Headers', 'x-signature,x-identity,X-Requested-With,Content-Type,Authorization');
2015-02-19 06:00:14 -08:00
next();
});
var allowCORS = function(req, res, next) {
if ('OPTIONS' == req.method) {
2015-03-06 15:11:28 -08:00
res.sendStatus(200);
2015-02-19 06:00:14 -08:00
res.end();
2015-03-06 15:11:28 -08:00
return;
2015-02-19 06:00:14 -08:00
}
2015-03-06 15:11:28 -08:00
next();
2015-02-19 06:00:14 -08:00
}
2015-05-07 12:45:17 -07:00
this.app.use(allowCORS);
this.app.enable('trust proxy');
2015-02-19 06:00:14 -08:00
var POST_LIMIT = 1024 * 100 /* Max POST 100 kb */ ;
2015-05-07 12:45:17 -07:00
this.app.use(bodyParser.json({
2015-02-19 06:00:14 -08:00
limit: POST_LIMIT
}));
2015-04-18 09:32:21 -07:00
if (opts.disableLogs) {
log.level = 'silent';
} else {
2015-02-21 22:46:47 -08:00
// TODO access.log
//var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'})
//app.use(morgan('combined', {stream: accessLogStream}))
2015-04-18 02:55:24 -07:00
// app.use(require('morgan')('dev'));
2015-05-07 12:45:17 -07:00
this.app.use(require('morgan')(':remote-addr :date[iso] ":method :url" :status :res[content-length] :response-time ":user-agent" '));
2015-02-21 22:46:47 -08:00
}
2015-02-19 06:00:14 -08:00
var router = express.Router();
function returnError(err, res, req) {
2015-02-20 12:32:19 -08:00
if (err instanceof WalletService.ClientError) {
2015-02-19 06:00:14 -08:00
var status = (err.code == 'NOTAUTHORIZED') ? 401 : 400;
2015-02-21 22:46:47 -08:00
if (!opts.disableLogs)
2015-02-26 08:08:11 -08:00
log.info('Client Err: ' + status + ' ' + req.url + ' ' + err);
2015-02-21 22:46:47 -08:00
2015-02-19 06:00:14 -08:00
res.status(status).json({
code: err.code,
2015-02-23 09:09:04 -08:00
message: err.message,
2015-02-19 06:00:14 -08:00
}).end();
} else {
var code, message;
if (_.isObject(err)) {
code = err.code;
message = err.message;
}
var m = message || err.toString();
2015-02-21 22:46:47 -08:00
if (!opts.disableLogs)
log.error('Err: ' + req.url + ' :' + code + ':' + m);
2015-02-19 06:00:14 -08:00
res.status(code || 500).json({
error: m,
}).end();
}
};
function getCredentials(req) {
var identity = req.header('x-identity');
if (!identity) return;
return {
copayerId: identity,
signature: req.header('x-signature'),
};
};
function getServerWithAuth(req, res, cb) {
var credentials = getCredentials(req);
2015-02-19 07:32:10 -08:00
if (!credentials)
2015-02-20 12:32:19 -08:00
return returnError(new WalletService.ClientError({
2015-02-19 07:32:10 -08:00
code: 'NOTAUTHORIZED'
}), res, req);
2015-02-19 06:00:14 -08:00
var auth = {
copayerId: credentials.copayerId,
message: req.method.toLowerCase() + '|' + req.url + '|' + JSON.stringify(req.body),
signature: credentials.signature,
};
2015-02-20 12:32:19 -08:00
WalletService.getInstanceWithAuth(auth, function(err, server) {
2015-02-19 06:00:14 -08:00
if (err) return returnError(err, res, req);
return cb(server);
});
};
router.post('/v1/wallets/', function(req, res) {
2015-02-20 12:32:19 -08:00
var server = WalletService.getInstance();
2015-02-19 06:00:14 -08:00
server.createWallet(req.body, function(err, walletId) {
if (err) return returnError(err, res, req);
res.json({
walletId: walletId,
});
});
});
router.post('/v1/wallets/:id/copayers/', function(req, res) {
req.body.walletId = req.params['id'];
2015-02-20 12:32:19 -08:00
var server = WalletService.getInstance();
2015-02-19 06:00:14 -08:00
server.joinWallet(req.body, function(err, result) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
router.put('/v1/copayers', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.replaceTemporaryRequestKey(req.body, function(err, result) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
});
2015-02-19 06:00:14 -08:00
router.get('/v1/wallets/', function(req, res) {
getServerWithAuth(req, res, function(server) {
var result = {};
async.parallel([
function(next) {
server.getWallet({}, function(err, wallet) {
if (err) return next(err);
result.wallet = wallet;
next();
});
},
function(next) {
server.getBalance({}, function(err, balance) {
if (err) return next(err);
result.balance = balance;
next();
});
},
function(next) {
server.getPendingTxs({}, function(err, pendingTxps) {
if (err) return next(err);
result.pendingTxps = pendingTxps;
next();
});
},
2015-04-27 11:55:42 -07:00
function(next) {
server.getPreferences({}, function(err, preferences) {
if (err) return next(err);
result.preferences = preferences;
next();
});
},
2015-02-19 06:00:14 -08:00
], function(err) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
});
2015-05-14 08:43:12 -07:00
router.get('/v1/preferences/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getPreferences({}, function(err, preferences) {
if (err) return returnError(err, res, req);
res.json(preferences);
});
});
});
router.put('/v1/preferences', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.savePreferences(req.body, function(err, result) {
if (err) return returnError(err, res, req);
res.json(result);
});
});
});
2015-02-19 06:00:14 -08:00
router.get('/v1/txproposals/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getPendingTxs({}, function(err, pendings) {
if (err) return returnError(err, res, req);
res.json(pendings);
});
});
});
router.post('/v1/txproposals/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.createTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
});
});
});
router.post('/v1/addresses/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.createAddress(req.body, function(err, address) {
if (err) return returnError(err, res, req);
res.json(address);
});
});
});
router.get('/v1/addresses/', function(req, res) {
getServerWithAuth(req, res, function(server) {
2015-02-22 08:04:23 -08:00
server.getMainAddresses({}, function(err, addresses) {
2015-02-19 06:00:14 -08:00
if (err) return returnError(err, res, req);
res.json(addresses);
});
});
});
router.get('/v1/balance/', function(req, res) {
getServerWithAuth(req, res, function(server) {
server.getBalance({}, function(err, balance) {
if (err) return returnError(err, res, req);
res.json(balance);
});
});
});
router.post('/v1/txproposals/:id/signatures/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.signTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
// TODO Check HTTP verb and URL name
router.post('/v1/txproposals/:id/broadcast/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.broadcastTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
router.post('/v1/txproposals/:id/rejections', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.rejectTx(req.body, function(err, txp) {
if (err) return returnError(err, res, req);
res.json(txp);
res.end();
});
});
});
router.delete('/v1/txproposals/:id/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.removePendingTx(req.body, function(err) {
if (err) return returnError(err, res, req);
2015-04-13 06:02:26 -07:00
res.json({
success: true
});
2015-02-19 06:00:14 -08:00
res.end();
});
});
});
2015-04-10 08:37:01 -07:00
router.get('/v1/txproposals/:id/', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
server.getTx(req.body, function(err, tx) {
if (err) return returnError(err, res, req);
res.json(tx);
res.end();
});
});
});
2015-02-21 19:12:05 -08:00
router.get('/v1/txhistory/', function(req, res) {
getServerWithAuth(req, res, function(server) {
2015-03-17 09:52:49 -07:00
var opts = {};
if (req.query.skip) opts.skip = +req.query.skip;
2015-03-17 16:02:13 -07:00
if (req.query.limit) opts.limit = +req.query.limit;
2015-03-17 09:52:49 -07:00
server.getTxHistory(opts, function(err, txs) {
2015-02-21 19:12:05 -08:00
if (err) return returnError(err, res, req);
res.json(txs);
2015-02-22 18:26:21 -08:00
res.end();
2015-02-21 19:12:05 -08:00
});
});
});
2015-04-02 07:28:16 -07:00
router.post('/v1/addresses/scan/', function(req, res) {
getServerWithAuth(req, res, function(server) {
2015-04-04 09:03:19 -07:00
server.startScan(req.body, function(err, started) {
2015-04-02 07:28:16 -07:00
if (err) return returnError(err, res, req);
2015-04-04 09:03:19 -07:00
res.json(started);
2015-04-02 07:28:16 -07:00
res.end();
});
});
});
2015-05-26 10:59:55 -07:00
router.get('/v1/stats/', function(req, res) {
2015-05-07 13:07:29 -07:00
var opts = {};
2015-05-26 10:59:55 -07:00
if (req.query.network) opts.network = req.query.network;
if (req.query.from) opts.from = req.query.from;
if (req.query.to) opts.to = req.query.to;
var stats = new Stats(opts);
stats.run(function(err, data) {
2015-05-04 13:36:49 -07:00
if (err) return returnError(err, res, req);
res.json(data);
res.end();
});
});
2015-05-07 12:45:17 -07:00
this.app.use(opts.basePath || '/bws/api', router);
2015-04-21 10:43:35 -07:00
2015-05-07 12:45:17 -07:00
WalletService.initialize(opts, cb);
2015-05-04 13:36:49 -07:00
2015-02-19 06:00:14 -08:00
};
module.exports = ExpressApp;