Merge pull request #382 from isocolsky/ref/sockets
Add notifications endpoint
This commit is contained in:
commit
31aa292135
|
@ -13,7 +13,7 @@ var Stats = require('./stats');
|
||||||
|
|
||||||
log.disableColor();
|
log.disableColor();
|
||||||
log.debug = log.verbose;
|
log.debug = log.verbose;
|
||||||
log.level = 'debug';
|
log.level = 'info';
|
||||||
|
|
||||||
var ExpressApp = function() {
|
var ExpressApp = function() {
|
||||||
this.app = express();
|
this.app = express();
|
||||||
|
@ -85,7 +85,8 @@ ExpressApp.prototype.start = function(opts, cb) {
|
||||||
message: err.message,
|
message: err.message,
|
||||||
}).end();
|
}).end();
|
||||||
} else {
|
} else {
|
||||||
var code = 500, message;
|
var code = 500,
|
||||||
|
message;
|
||||||
if (_.isObject(err)) {
|
if (_.isObject(err)) {
|
||||||
code = err.code || err.statusCode;
|
code = err.code || err.statusCode;
|
||||||
message = err.message || err.body;
|
message = err.message || err.body;
|
||||||
|
@ -430,10 +431,25 @@ ExpressApp.prototype.start = function(opts, cb) {
|
||||||
|
|
||||||
router.get('/v1/version/', function(req, res) {
|
router.get('/v1/version/', function(req, res) {
|
||||||
var server = getServer(req, res);
|
var server = getServer(req, res);
|
||||||
res.json( { serviceVersion: server.serviceVersion } );
|
res.json({
|
||||||
|
serviceVersion: server.serviceVersion
|
||||||
|
});
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/v1/notifications/', function(req, res) {
|
||||||
|
getServerWithAuth(req, res, function(server) {
|
||||||
|
var opts = {
|
||||||
|
minTs: +Date.now() - (60 * 1000),
|
||||||
|
notificationId: req.query.notificationId,
|
||||||
|
};
|
||||||
|
server.getNotifications(opts, function(err, notifications) {
|
||||||
|
if (err) return returnError(err, res, req);
|
||||||
|
res.json(notifications);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.app.use(opts.basePath || '/bws/api', router);
|
this.app.use(opts.basePath || '/bws/api', router);
|
||||||
|
|
||||||
WalletService.initialize(opts, cb);
|
WalletService.initialize(opts, cb);
|
||||||
|
|
|
@ -32,6 +32,7 @@ Notification.create = function(opts) {
|
||||||
|
|
||||||
x.version = '1.0.0';
|
x.version = '1.0.0';
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
||||||
x.createdOn = Math.floor(now / 1000);
|
x.createdOn = Math.floor(now / 1000);
|
||||||
x.id = _.padLeft(now, 14, '0') + _.padLeft(opts.ticker || 0, 4, '0');
|
x.id = _.padLeft(now, 14, '0') + _.padLeft(opts.ticker || 0, 4, '0');
|
||||||
x.type = opts.type || 'general';
|
x.type = opts.type || 'general';
|
||||||
|
|
|
@ -1641,24 +1641,23 @@ WalletService.prototype.getTxs = function(opts, cb) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves notifications in the range (maxTs-minTs).
|
* Retrieves notifications after a specific id or from a given ts (whichever is more recent).
|
||||||
* Times are in UNIX EPOCH. Order is assured even for events with the same time
|
|
||||||
*
|
*
|
||||||
* @param {Object} opts.minTs (defaults to 0)
|
* @param {Object} opts
|
||||||
* @param {Object} opts.maxTs (defaults to now)
|
* @param {Object} opts.notificationId (optional)
|
||||||
* @param {Object} opts.limit
|
* @param {Object} opts.minTs (optional) - default 0.
|
||||||
* @param {Object} opts.reverse (default false)
|
|
||||||
* @returns {Notification[]} Notifications
|
* @returns {Notification[]} Notifications
|
||||||
*/
|
*/
|
||||||
WalletService.prototype.getNotifications = function(opts, cb) {
|
WalletService.prototype.getNotifications = function(opts, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.storage.fetchNotifications(self.walletId, opts, function(err, notifications) {
|
opts = opts || {};
|
||||||
|
|
||||||
|
self.storage.fetchNotifications(self.walletId, opts.notificationId, opts.minTs || 0, function(err, notifications) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
return cb(null, notifications);
|
return cb(null, notifications);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
WalletService.prototype._normalizeTxHistory = function(txs) {
|
WalletService.prototype._normalizeTxHistory = function(txs) {
|
||||||
var now = Math.floor(Date.now() / 1000);
|
var now = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
|
|
|
@ -315,6 +315,44 @@ Storage.prototype.fetchNotifications = function(walletId, opts, cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves notifications after a specific id or from a given ts (whichever is more recent).
|
||||||
|
*
|
||||||
|
* @param {String} notificationId
|
||||||
|
* @param {Number} minTs
|
||||||
|
* @returns {Notification[]} Notifications
|
||||||
|
*/
|
||||||
|
Storage.prototype.fetchNotifications = function(walletId, notificationId, minTs, cb) {
|
||||||
|
function makeId(timestamp) {
|
||||||
|
return _.padLeft(timestamp, 14, '0') + _.repeat('0', 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var minId = makeId(minTs);
|
||||||
|
if (notificationId) {
|
||||||
|
minId = notificationId > minId ? notificationId : minId;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.db.collection(collections.NOTIFICATIONS)
|
||||||
|
.find({
|
||||||
|
walletId: walletId,
|
||||||
|
id: {
|
||||||
|
$gt: minId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.sort({
|
||||||
|
id: 1
|
||||||
|
})
|
||||||
|
.toArray(function(err, result) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
if (!result) return cb();
|
||||||
|
var notifications = _.map(result, function(notification) {
|
||||||
|
return Model.Notification.fromObj(notification);
|
||||||
|
});
|
||||||
|
return cb(null, notifications);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: remove walletId from signature
|
// TODO: remove walletId from signature
|
||||||
Storage.prototype.storeNotification = function(walletId, notification, cb) {
|
Storage.prototype.storeNotification = function(walletId, notification, cb) {
|
||||||
|
|
26
package.json
26
package.json
|
@ -2,7 +2,7 @@
|
||||||
"name": "bitcore-wallet-service",
|
"name": "bitcore-wallet-service",
|
||||||
"description": "A service for Mutisig HD Bitcoin Wallets",
|
"description": "A service for Mutisig HD Bitcoin Wallets",
|
||||||
"author": "BitPay Inc",
|
"author": "BitPay Inc",
|
||||||
"version": "0.3.0",
|
"version": "0.4.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bitcoin",
|
"bitcoin",
|
||||||
"copay",
|
"copay",
|
||||||
|
@ -64,18 +64,14 @@
|
||||||
"coveralls": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
|
"coveralls": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
|
||||||
},
|
},
|
||||||
"bitcoreNode": "./bitcorenode",
|
"bitcoreNode": "./bitcorenode",
|
||||||
"contributors": [
|
"contributors": [{
|
||||||
{
|
"name": "Braydon Fuller",
|
||||||
"name": "Braydon Fuller",
|
"email": "braydon@bitpay.com"
|
||||||
"email": "braydon@bitpay.com"
|
}, {
|
||||||
},
|
"name": "Ivan Socolsky",
|
||||||
{
|
"email": "ivan@bitpay.com"
|
||||||
"name": "Ivan Socolsky",
|
}, {
|
||||||
"email": "ivan@bitpay.com"
|
"name": "Matias Alejo Garcia",
|
||||||
},
|
"email": "ematiu@gmail.com"
|
||||||
{
|
}]
|
||||||
"name": "Matias Alejo Garcia",
|
|
||||||
"email": "ematiu@gmail.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,22 @@ describe('ExpressApp', function() {
|
||||||
describe('Routes', function() {
|
describe('Routes', function() {
|
||||||
var testPort = 3239;
|
var testPort = 3239;
|
||||||
var testHost = 'http://127.0.0.1';
|
var testHost = 'http://127.0.0.1';
|
||||||
|
var httpServer;
|
||||||
|
|
||||||
|
function start(ExpressApp, done) {
|
||||||
|
var app = new ExpressApp();
|
||||||
|
httpServer = http.Server(app.app);
|
||||||
|
|
||||||
|
app.start(config, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
httpServer.listen(testPort);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
httpServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
it('/v2/wallets', function(done) {
|
it('/v2/wallets', function(done) {
|
||||||
var server = {
|
var server = {
|
||||||
|
@ -49,20 +65,15 @@ describe('ExpressApp', function() {
|
||||||
getInstanceWithAuth: sinon.stub().callsArgWith(1, null, server),
|
getInstanceWithAuth: sinon.stub().callsArgWith(1, null, server),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var app = new TestExpressApp();
|
start(TestExpressApp, function() {
|
||||||
var httpServer = http.Server(app.app);
|
|
||||||
|
|
||||||
app.start(config, function(err) {
|
|
||||||
should.not.exist(err);
|
|
||||||
httpServer.listen(testPort);
|
|
||||||
var requestOptions = {
|
var requestOptions = {
|
||||||
url: testHost + ':' + testPort + config.basePath + '/v1/wallets',
|
url: testHost + ':' + testPort + config.basePath + '/v2/wallets',
|
||||||
headers: {
|
headers: {
|
||||||
'x-identity': 'identity',
|
'x-identity': 'identity',
|
||||||
'x-signature': 'signature'
|
'x-signature': 'signature'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
request(requestOptions, function(err, response, body){
|
request(requestOptions, function(err, response, body) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
response.statusCode.should.equal(200);
|
response.statusCode.should.equal(200);
|
||||||
body.should.equal('{}');
|
body.should.equal('{}');
|
||||||
|
@ -70,6 +81,41 @@ describe('ExpressApp', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('/v1/notifications', function(done) {
|
||||||
|
var clock = sinon.useFakeTimers(1234000, 'Date');
|
||||||
|
|
||||||
|
var server = {
|
||||||
|
getNotifications: sinon.stub().callsArgWith(1, null, {})
|
||||||
|
};
|
||||||
|
var TestExpressApp = proxyquire('../lib/expressapp', {
|
||||||
|
'./server': {
|
||||||
|
initialize: sinon.stub().callsArg(1),
|
||||||
|
getInstanceWithAuth: sinon.stub().callsArgWith(1, null, server),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
start(TestExpressApp, function() {
|
||||||
|
var requestOptions = {
|
||||||
|
url: testHost + ':' + testPort + config.basePath + '/v1/notifications' + '?notificationId=123&minTs=0',
|
||||||
|
headers: {
|
||||||
|
'x-identity': 'identity',
|
||||||
|
'x-signature': 'signature'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
request(requestOptions, function(err, response, body) {
|
||||||
|
should.not.exist(err);
|
||||||
|
response.statusCode.should.equal(200);
|
||||||
|
body.should.equal('{}');
|
||||||
|
server.getNotifications.calledWith({
|
||||||
|
notificationId: '123',
|
||||||
|
minTs: 1234000 - 60000, // override minTs argument with a hardcoded 60 seconds span
|
||||||
|
}).should.be.true;
|
||||||
|
|
||||||
|
clock.restore();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3875,75 +3875,103 @@ describe('Wallet service', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Notifications', function() {
|
describe('#getNotifications', function() {
|
||||||
|
var clock;
|
||||||
var server, wallet;
|
var server, wallet;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
|
clock = sinon.useFakeTimers(10 * 1000, 'Date');
|
||||||
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
helpers.stubUtxos(server, wallet, _.range(4), function() {
|
helpers.stubUtxos(server, wallet, _.range(4), function() {
|
||||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.01, TestData.copayers[0].privKey_1H_0);
|
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.01, TestData.copayers[0].privKey_1H_0);
|
||||||
async.eachSeries(_.range(3), function(i, next) {
|
async.eachSeries(_.range(3), function(i, next) {
|
||||||
|
clock.tick(25 * 1000);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
clock.tick(20 * 1000);
|
||||||
return done(err);
|
return done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
clock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('should pull the last 4 notifications after 3 TXs', function(done) {
|
it('should pull all notifications', function(done) {
|
||||||
server.getNotifications({
|
server.getNotifications({}, function(err, notifications) {
|
||||||
limit: 4,
|
|
||||||
reverse: true,
|
|
||||||
}, function(err, notifications) {
|
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
types.should.deep.equal(['NewTxProposal', 'NewTxProposal', 'NewTxProposal', 'NewAddress']);
|
types.should.deep.equal(['NewCopayer', 'NewAddress', 'NewAddress', 'NewTxProposal', 'NewTxProposal', 'NewTxProposal']);
|
||||||
var walletIds = _.uniq(_.pluck(notifications, 'walletId'));
|
var walletIds = _.uniq(_.pluck(notifications, 'walletId'));
|
||||||
walletIds.length.should.equal(1);
|
walletIds.length.should.equal(1);
|
||||||
walletIds[0].should.equal(wallet.id);
|
walletIds[0].should.equal(wallet.id);
|
||||||
var creators = _.uniq(_.pluck(notifications, 'creatorId'));
|
var creators = _.uniq(_.compact(_.pluck(notifications, 'creatorId')));
|
||||||
creators.length.should.equal(1);
|
creators.length.should.equal(1);
|
||||||
creators[0].should.equal(wallet.copayers[0].id);
|
creators[0].should.equal(wallet.copayers[0].id);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pull the last 4 notifications, using now', function(done) {
|
it('should pull notifications in the last 60 seconds', function(done) {
|
||||||
server.getNotifications({
|
server.getNotifications({
|
||||||
limit: 4,
|
minTs: +Date.now() - (60 * 1000),
|
||||||
reverse: true,
|
|
||||||
maxTs: Date.now() / 1000,
|
|
||||||
minTs: Date.now() / 1000 - 1000,
|
|
||||||
}, function(err, notifications) {
|
}, function(err, notifications) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
types.should.deep.equal(['NewTxProposal', 'NewTxProposal', 'NewTxProposal', 'NewAddress']);
|
types.should.deep.equal(['NewTxProposal', 'NewTxProposal']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pull all notifications after wallet creation', function(done) {
|
it('should pull notifications after a given notification id', function(done) {
|
||||||
server.getNotifications({
|
server.getNotifications({}, function(err, notifications) {
|
||||||
minTs: 0,
|
|
||||||
}, function(err, notifications) {
|
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
var types = _.pluck(notifications, 'type');
|
var from = _.first(_.takeRight(notifications, 2)).id; // second to last
|
||||||
types[0].should.equal('NewCopayer');
|
server.getNotifications({
|
||||||
types[types.length - 1].should.equal('NewTxProposal');
|
notificationId: from,
|
||||||
|
minTs: +Date.now() - (60 * 1000),
|
||||||
|
}, function(err, res) {
|
||||||
|
should.not.exist(err);
|
||||||
|
res.length.should.equal(1);
|
||||||
|
res[0].id.should.equal(_.first(_.takeRight(notifications)).id);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty if no notifications found after a given id', function(done) {
|
||||||
|
server.getNotifications({}, function(err, notifications) {
|
||||||
|
should.not.exist(err);
|
||||||
|
var from = _.first(_.takeRight(notifications)).id; // last one
|
||||||
|
server.getNotifications({
|
||||||
|
notificationId: from,
|
||||||
|
}, function(err, res) {
|
||||||
|
should.not.exist(err);
|
||||||
|
res.length.should.equal(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty if no notifications exist in the given timespan', function(done) {
|
||||||
|
clock.tick(100 * 1000);
|
||||||
|
server.getNotifications({
|
||||||
|
minTs: +Date.now() - (60 * 1000),
|
||||||
|
}, function(err, res) {
|
||||||
|
should.not.exist(err);
|
||||||
|
res.length.should.equal(0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain walletId & creatorId on NewCopayer', function(done) {
|
it('should contain walletId & creatorId on NewCopayer', function(done) {
|
||||||
server.getNotifications({
|
server.getNotifications({}, function(err, notifications) {
|
||||||
minTs: 0,
|
|
||||||
}, function(err, notifications) {
|
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
var newCopayer = notifications[0];
|
var newCopayer = notifications[0];
|
||||||
newCopayer.type.should.equal('NewCopayer');
|
newCopayer.type.should.equal('NewCopayer');
|
||||||
|
@ -3963,12 +3991,12 @@ describe('Wallet service', function() {
|
||||||
signatures: signatures,
|
signatures: signatures,
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
server.getNotifications({
|
server.getNotifications({
|
||||||
limit: 3,
|
minTs: Date.now(),
|
||||||
reverse: true,
|
|
||||||
}, function(err, notifications) {
|
}, function(err, notifications) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
notifications.length.should.equal(2);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
types.should.deep.equal(['TxProposalFinallyAccepted', 'TxProposalAcceptedBy', 'NewTxProposal']);
|
types.should.deep.equal(['TxProposalAcceptedBy', 'TxProposalFinallyAccepted']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3983,12 +4011,12 @@ describe('Wallet service', function() {
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
server.getNotifications({
|
server.getNotifications({
|
||||||
limit: 2,
|
minTs: Date.now(),
|
||||||
reverse: true,
|
|
||||||
}, function(err, notifications) {
|
}, function(err, notifications) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
notifications.length.should.equal(2);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
types.should.deep.equal(['TxProposalFinallyRejected', 'TxProposalRejectedBy']);
|
types.should.deep.equal(['TxProposalRejectedBy', 'TxProposalFinallyRejected']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4011,12 +4039,12 @@ describe('Wallet service', function() {
|
||||||
}, function(err, txp) {
|
}, function(err, txp) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
server.getNotifications({
|
server.getNotifications({
|
||||||
limit: 3,
|
minTs: Date.now(),
|
||||||
reverse: true,
|
|
||||||
}, function(err, notifications) {
|
}, function(err, notifications) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
notifications.length.should.equal(3);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
types.should.deep.equal(['NewOutgoingTx', 'TxProposalFinallyAccepted', 'TxProposalAcceptedBy']);
|
types.should.deep.equal(['TxProposalAcceptedBy', 'TxProposalFinallyAccepted', 'NewOutgoingTx']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4043,12 +4071,12 @@ describe('Wallet service', function() {
|
||||||
}, function(err, txp) {
|
}, function(err, txp) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
server.getNotifications({
|
server.getNotifications({
|
||||||
limit: 3,
|
minTs: Date.now(),
|
||||||
reverse: true,
|
|
||||||
}, function(err, notifications) {
|
}, function(err, notifications) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
notifications.length.should.equal(3);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
types.should.deep.equal(['NewOutgoingTxByThirdParty', 'TxProposalFinallyAccepted', 'TxProposalAcceptedBy']);
|
types.should.deep.equal(['TxProposalAcceptedBy', 'TxProposalFinallyAccepted', 'NewOutgoingTxByThirdParty']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4101,7 +4129,7 @@ describe('Wallet service', function() {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(next) {
|
function(next) {
|
||||||
server.storage.fetchNotifications(wallet.id, {}, function(err, items) {
|
server.getNotifications({}, function(err, items) {
|
||||||
items.length.should.equal(0);
|
items.length.should.equal(0);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue