Browse Source

all tests passing

activeAddress
Ivan Socolsky 10 years ago
parent
commit
ea3d251c0d
  1. 2
      lib/server.js
  2. 56
      lib/storage_mongo.js
  3. 266
      test/integration/server.js

2
lib/server.js

@ -942,7 +942,7 @@ WalletService.prototype.getPendingTxs = function(opts, cb) {
* @param {Object} opts.minTs (defaults to 0)
* @param {Object} opts.maxTs (defaults to now)
* @param {Object} opts.limit
* @returns {TxProposal[]} Transaction proposals, first newer
* @returns {TxProposal[]} Transaction proposals, newer first
*/
WalletService.prototype.getTxs = function(opts, cb) {
var self = this;

56
lib/storage_mongo.js

@ -12,6 +12,13 @@ var mongodb = require('mongodb');
var Model = require('./model');
var collections = {
WALLETS: 'wallets',
TXS: 'txs',
ADDRESSES: 'addresses',
NOTIFICATIONS: 'notifications',
};
var Storage = function(opts) {
opts = opts || {};
this.db = opts.db;
@ -30,7 +37,7 @@ var Storage = function(opts) {
};
Storage.prototype.fetchWallet = function(id, cb) {
this.db.collection('wallets').findOne({
this.db.collection(collections.WALLETS).findOne({
id: id
}, function(err, result) {
if (err) return cb(err);
@ -40,7 +47,7 @@ Storage.prototype.fetchWallet = function(id, cb) {
};
Storage.prototype.storeWallet = function(wallet, cb) {
this.db.collection('wallets').update({
this.db.collection(collections.WALLETS).update({
id: wallet.id
}, wallet, {
w: 1,
@ -53,7 +60,7 @@ Storage.prototype.storeWalletAndUpdateCopayersLookup = function(wallet, cb) {
};
Storage.prototype.fetchCopayerLookup = function(copayerId, cb) {
this.db.collection('wallets').findOne({
this.db.collection(collections.WALLETS).findOne({
'copayers.id': copayerId
}, {
fields: {
@ -91,7 +98,7 @@ Storage.prototype._completeTxData = function(walletId, txs, cb) {
Storage.prototype.fetchTx = function(walletId, txProposalId, cb) {
var self = this;
this.db.collection('txs').findOne({
this.db.collection(collections.TXS).findOne({
id: txProposalId,
walletId: walletId
}, function(err, result) {
@ -105,11 +112,11 @@ Storage.prototype.fetchTx = function(walletId, txProposalId, cb) {
Storage.prototype.fetchPendingTxs = function(walletId, cb) {
var self = this;
this.db.collection('txs').find({
this.db.collection(collections.TXS).find({
walletId: walletId,
isPending: true
}).sort({
createdOn: 1
createdOn: -1
}).toArray(function(err, result) {
if (err) return cb(err);
if (!result) return cb();
@ -145,8 +152,8 @@ Storage.prototype.fetchTxs = function(walletId, opts, cb) {
var mods = {};
if (_.isNumber(opts.limit)) mods.limit = opts.limit;
this.db.collection('txs').find(filter, mods).sort({
createdOn: 1
this.db.collection(collections.TXS).find(filter, mods).sort({
createdOn: -1
}).toArray(function(err, result) {
if (err) return cb(err);
if (!result) return cb();
@ -165,6 +172,7 @@ Storage.prototype.fetchTxs = function(walletId, opts, cb) {
* @param opts.minTs
* @param opts.maxTs
* @param opts.limit
* @param opts.reverse
*/
Storage.prototype.fetchNotifications = function(walletId, opts, cb) {
var self = this;
@ -183,8 +191,8 @@ Storage.prototype.fetchNotifications = function(walletId, opts, cb) {
var mods = {};
if (_.isNumber(opts.limit)) mods.limit = opts.limit;
this.db.collection('notifications').find(filter, mods).sort({
createdOn: 1
this.db.collection(collections.NOTIFICATIONS).find(filter, mods).sort({
id: opts.reverse ? -1 : 1,
}).toArray(function(err, result) {
if (err) return cb(err);
if (!result) return cb();
@ -198,7 +206,7 @@ Storage.prototype.fetchNotifications = function(walletId, opts, cb) {
// TODO: remove walletId from signature
Storage.prototype.storeNotification = function(walletId, notification, cb) {
this.db.collection('notifications').insert(notification, {
this.db.collection(collections.NOTIFICATIONS).insert(notification, {
w: 1
}, cb);
};
@ -206,7 +214,7 @@ Storage.prototype.storeNotification = function(walletId, notification, cb) {
// TODO: remove walletId from signature
Storage.prototype.storeTx = function(walletId, txp, cb) {
txp.isPending = txp.isPending(); // Persist attribute to use when querying
this.db.collection('txs').update({
this.db.collection(collections.TXS).update({
id: txp.id,
walletId: walletId
}, txp, {
@ -216,7 +224,7 @@ Storage.prototype.storeTx = function(walletId, txp, cb) {
};
Storage.prototype.removeTx = function(walletId, txProposalId, cb) {
this.db.collection('txs').findAndRemove({
this.db.collection(collections.TXS).findAndRemove({
id: txProposalId,
walletId: walletId
}, {
@ -230,22 +238,22 @@ Storage.prototype.removeWallet = function(walletId, cb) {
async.parallel([
function(next) {
this.db.collections('wallets').findAndRemove({
self.db.collection(collections.WALLETS).findAndRemove({
id: walletId
}, next);
},
function(next) {
this.db.collections('addresses').findAndRemove({
self.db.collection(collections.ADDRESSES).remove({
walletId: walletId
}, next);
},
function(next) {
this.db.collections('txs').findAndRemove({
self.db.collection(collections.TXS).remove({
walletId: walletId
}, next);
},
function(next) {
this.db.collections('notifications').findAndRemove({
self.db.collection(collections.NOTIFICATIONS).remove({
walletId: walletId
}, next);
},
@ -256,7 +264,7 @@ Storage.prototype.removeWallet = function(walletId, cb) {
Storage.prototype.fetchAddresses = function(walletId, cb) {
var self = this;
this.db.collection('addresses').find({
this.db.collection(collections.ADDRESSES).find({
walletId: walletId,
}).sort({
createdOn: 1
@ -272,7 +280,9 @@ Storage.prototype.fetchAddresses = function(walletId, cb) {
Storage.prototype.storeAddressAndWallet = function(wallet, addresses, cb) {
var self = this;
this.db.collection('addresses').insert([].concat(addresses), {
var addresses = [].concat(addresses);
if (addresses.length == 0) return cb();
this.db.collection(collections.ADDRESSES).insert(addresses, {
w: 1
}, function(err) {
if (err) return cb(err);
@ -282,14 +292,16 @@ Storage.prototype.storeAddressAndWallet = function(wallet, addresses, cb) {
Storage.prototype._dump = function(cb, fn) {
fn = fn || console.log;
cb = cb || function() {};
var self = this;
this.db.collections(function(err, collections) {
if (err) return cb(err);
async.eachSeries(collections, function(col, next) {
fn('--------' + col);
col.find().toArray(function(err, item) {
fn(item);
col.find().toArray(function(err, items) {
fn('--------', col.s.name);
fn(items);
fn('------------------------------------------------------------------\n\n');
next(err);
});
}, cb);

266
test/integration/server.js

@ -9,13 +9,14 @@ var sinon = require('sinon');
var should = chai.should();
var levelup = require('levelup');
var memdown = require('memdown');
var mongodb = require('mongodb');
var log = require('npmlog');
log.debug = log.verbose;
var Utils = require('../../lib/utils');
var WalletUtils = require('bitcore-wallet-utils');
var Bitcore = WalletUtils.Bitcore;
var Storage = require('../../lib/storage');
var Storage = require('../../lib/storage_mongo');
var BlockchainMonitor = require('../../lib/blockchainmonitor');
var Wallet = require('../../lib/model/wallet');
@ -208,24 +209,56 @@ helpers.createAddresses = function(server, wallet, main, change, cb) {
var db, storage, blockchainExplorer;
describe('Wallet service', function() {
beforeEach(function() {
db = levelup(memdown, {
valueEncoding: 'json'
function openDb(cb) {
function dropDb(cb) {
db.dropDatabase(function(err) {
should.not.exist(err);
return cb();
});
storage = new Storage({
db: db
};
if (db) {
return dropDb(cb);
} else {
var url = 'mongodb://localhost:27017/bws';
mongodb.MongoClient.connect(url, function(err, _db) {
should.not.exist(err);
db = _db;
return dropDb(cb);
});
blockchainExplorer = sinon.stub();
}
};
WalletService.initialize({
storage: storage,
blockchainExplorer: blockchainExplorer,
function closeDb(cb) {
if (db) {
db.close(true, function(err) {
should.not.exist(err);
db = null;
return cb();
});
helpers.offset = 0;
});
} else {
return cb();
}
};
describe('Wallet service', function() {
beforeEach(function(done) {
openDb(function() {
storage = new Storage({
db: db
});
blockchainExplorer = sinon.stub();
WalletService.initialize({
storage: storage,
blockchainExplorer: blockchainExplorer,
});
helpers.offset = 0;
done();
});
});
after(function(done) {
closeDb(done);
});
describe('#getInstanceWithAuth', function() {
beforeEach(function() {});
@ -1172,6 +1205,7 @@ describe('Wallet service', function() {
helpers.stubUtxos(server, wallet, _.range(1, 9), function() {
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
txid = tx.id;
@ -1814,9 +1848,7 @@ describe('Wallet service', function() {
var server, wallet, clock;
beforeEach(function(done) {
if (server) return done();
this.timeout(5000);
console.log('\tCreating TXS...');
clock = sinon.useFakeTimers();
helpers.createAndJoinWallet(1, 1, function(s, w) {
server = s;
@ -1824,7 +1856,7 @@ describe('Wallet service', function() {
helpers.stubUtxos(server, wallet, _.range(10), function() {
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.1, null, TestData.copayers[0].privKey_1H_0);
async.eachSeries(_.range(10), function(i, next) {
clock.tick(10000);
clock.tick(10 * 1000);
server.createTx(txOpts, function(err, tx) {
next();
});
@ -1883,17 +1915,18 @@ describe('Wallet service', function() {
});
it('should txs from times 50 to 70', function(done) {
server.getTxs({
minTs: 50,
maxTs: 70,
}, function(err, txps) {
should.not.exist(err);
var times = _.pluck(txps, 'createdOn');
times.should.deep.equal([70, 60, 50]);
done();
it('should txs from times 50 to 70',
function(done) {
server.getTxs({
minTs: 50,
maxTs: 70,
}, function(err, txps) {
should.not.exist(err);
var times = _.pluck(txps, 'createdOn');
times.should.deep.equal([70, 60, 50]);
done();
});
});
});
});
describe('Notifications', function() {
@ -2073,62 +2106,110 @@ describe('Wallet service', function() {
});
});
});
it('should delete a wallet', function(done) {
var i = 0;
var count = function() {
return ++i;
};
server.storage._dump(function() {
i.should.above(1);
server.removeWallet({}, function(err) {
i = 0;
server.storage._dump(function() {
server.storage._dump();
i.should.equal(0);
server.removeWallet({}, function(err) {
should.not.exist(err);
server.getWallet({}, function(err, w) {
should.exist(err);
err.message.should.equal('Wallet not found');
should.not.exist(w);
async.parallel([
function(next) {
server.storage.fetchAddresses(wallet.id, function(err, items) {
items.length.should.equal(0);
next();
});
},
function(next) {
server.storage.fetchTxs(wallet.id, {}, function(err, items) {
items.length.should.equal(0);
next();
});
},
function(next) {
server.storage.fetchNotifications(wallet.id, {}, function(err, items) {
items.length.should.equal(0);
next();
});
},
], function(err) {
should.not.exist(err);
done();
}, count);
});
});
}, count);
});
});
// creates 2 wallet, and deletes only 1.
it('should delete a wallet, and only that wallet', function(done) {
var i = 0;
var db = [];
var cat = function(data) {
db.push(data);
};
server.storage._dump(function() {
var before = _.clone(db);
db.length.should.above(1);
helpers.offset = 1;
helpers.createAndJoinWallet(2, 3, function(s, w) {
server = s;
wallet = w;
helpers.stubUtxos(server, wallet, _.range(2), function() {
var txOpts = {
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: helpers.toSatoshi(0.1),
};
async.eachSeries(_.range(2), function(i, next) {
server.createTx(txOpts, function(err, tx) {
next();
});
}, function() {
server.removeWallet({}, function(err) {
db = [];
server.storage._dump(function() {
var after = _.clone(db);
after.should.deep.equal(before);
done();
}, cat);
});
}, cat);
var server2, wallet2;
async.series([
function(next) {
helpers.offset = 1;
helpers.createAndJoinWallet(1, 1, function(s, w) {
server2 = s;
wallet2 = w;
helpers.stubUtxos(server2, wallet2, _.range(1, 3), function() {
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.1, 'some message', TestData.copayers[1].privKey_1H_0);
async.eachSeries(_.range(2), function(i, next) {
server2.createTx(txOpts, function(err, tx) {
should.not.exist(err);
next(err);
});
}, next);
});
});
});
}, cat);
},
function(next) {
server.removeWallet({}, next);
},
function(next) {
server.getWallet({}, function(err, wallet) {
should.exist(err);
err.message.should.contain('not found');
next();
});
},
function(next) {
server2.getWallet({}, function(err, wallet) {
should.not.exist(err);
should.exist(wallet);
wallet.id.should.equal(wallet2.id);
next();
});
},
function(next) {
server2.getMainAddresses({}, function(err, addresses) {
should.not.exist(err);
should.exist(addresses);
addresses.length.should.above(0);
next();
});
},
function(next) {
server2.getTxs({}, function(err, txs) {
should.not.exist(err);
should.exist(txs);
txs.length.should.equal(2);
next();
});
},
function(next) {
server2.getNotifications({}, function(err, notifications) {
should.not.exist(err);
should.exist(notifications);
notifications.length.should.above(0);
next();
});
},
], function(err) {
should.not.exist(err);
done();
});
});
});
@ -2967,29 +3048,32 @@ describe('Wallet service', function() {
describe('Blockchain monitor', function() {
var addressSubscriber;
beforeEach(function() {
db = levelup(memdown, {
valueEncoding: 'json'
});
storage = new Storage({
db: db
});
blockchainExplorer = sinon.stub();
WalletService.initialize({
storage: storage,
blockchainExplorer: blockchainExplorer,
});
helpers.offset = 0;
beforeEach(function(done) {
addressSubscriber = sinon.stub();
addressSubscriber.subscribe = sinon.stub();
sinon.stub(BlockchainMonitor.prototype, '_getAddressSubscriber').onFirstCall().returns(addressSubscriber);
});
openDb(function() {
storage = new Storage({
db: db
});
blockchainExplorer = sinon.stub();
WalletService.initialize({
storage: storage,
blockchainExplorer: blockchainExplorer,
});
helpers.offset = 0;
done();
});
});
afterEach(function() {
BlockchainMonitor.prototype._getAddressSubscriber.restore();
});
after(function(done) {
closeDb(done);
});
it('should subscribe wallet', function(done) {
var monitor = new BlockchainMonitor();

Loading…
Cancel
Save