store cached data in db
This commit is contained in:
parent
3874d14f71
commit
94a376ca33
|
@ -992,8 +992,6 @@ WalletService.prototype._getBalanceFromAddresses = function(addresses, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
var prioritaryAddresses;
|
||||
|
||||
/**
|
||||
* Get wallet balance.
|
||||
* @param {Object} opts
|
||||
|
@ -1009,11 +1007,15 @@ WalletService.prototype.getBalance = function(opts, cb) {
|
|||
|
||||
// Update cache
|
||||
var addressIndex = _.indexBy(addresses, 'address');
|
||||
prioritaryAddresses = _.map(_.pluck(balance.byAddress, 'address'), function(addrStr) {
|
||||
var freshAddresses = _.map(_.pluck(balance.byAddress, 'address'), function(addrStr) {
|
||||
return addressIndex[addrStr];
|
||||
});
|
||||
|
||||
return cb(null, balance);
|
||||
self.storage.storeCacheData(self.walletId, 'freshAddresses', freshAddresses, function(err) {
|
||||
if (err) {
|
||||
log.warn('Could not update wallet cache', err);
|
||||
}
|
||||
return cb(null, balance);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -1027,20 +1029,24 @@ WalletService.prototype.getBalance = function(opts, cb) {
|
|||
WalletService.prototype.getBalance2Steps = function(opts, cb) {
|
||||
var self = this;
|
||||
|
||||
if (!prioritaryAddresses) return self.getBalance(opts, cb);
|
||||
|
||||
self._getBalanceFromAddresses(prioritaryAddresses, function(err, partialBalance) {
|
||||
if (err) return cb(err);
|
||||
cb(null, partialBalance);
|
||||
setTimeout(function() {
|
||||
self.getBalance(opts, function(err, fullBalance) {
|
||||
if (err) return;
|
||||
if (!_.isEqual(partialBalance, fullBalance)) {
|
||||
console.log('*** [server.js ln1015] ACTUALIZAR BALANCE!!!!, partialBalance, fullBalance:', partialBalance, fullBalance); // TODO
|
||||
}
|
||||
self.storage.fetchCacheData(self.walletId, 'freshAddresses', function(err, freshAddresses) {
|
||||
if (err || _.isEmpty(freshAddresses)) {
|
||||
return self.getBalance(opts, cb);
|
||||
} else {
|
||||
self._getBalanceFromAddresses(freshAddresses, function(err, partialBalance) {
|
||||
if (err) return cb(err);
|
||||
cb(null, partialBalance);
|
||||
setTimeout(function() {
|
||||
self.getBalance(opts, function(err, fullBalance) {
|
||||
if (err) return;
|
||||
if (!_.isEqual(partialBalance, fullBalance)) {
|
||||
self._notify('BalanceUpdated', fullBalance);
|
||||
}
|
||||
});
|
||||
}, 1);
|
||||
return;
|
||||
});
|
||||
}, 1);
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ var collections = {
|
|||
COPAYERS_LOOKUP: 'copayers_lookup',
|
||||
PREFERENCES: 'preferences',
|
||||
EMAIL_QUEUE: 'email_queue',
|
||||
CACHE: 'cache',
|
||||
};
|
||||
|
||||
var Storage = function(opts) {
|
||||
|
@ -56,6 +57,10 @@ Storage.prototype._createIndexes = function() {
|
|||
this.db.collection(collections.EMAIL_QUEUE).createIndex({
|
||||
notificationId: 1,
|
||||
});
|
||||
this.db.collection(collections.CACHE).createIndex({
|
||||
walletId: 1,
|
||||
key: 1,
|
||||
});
|
||||
};
|
||||
|
||||
Storage.prototype.connect = function(opts, cb) {
|
||||
|
@ -501,6 +506,37 @@ Storage.prototype.fetchEmailByNotification = function(notificationId, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
Storage.prototype.storeCacheData = function(walletId, key, value, cb) {
|
||||
var self = this;
|
||||
|
||||
var record = {
|
||||
walletId: walletId,
|
||||
key: key,
|
||||
data: value
|
||||
};
|
||||
self.db.collection(collections.CACHE).update({
|
||||
walletId: walletId,
|
||||
key: key,
|
||||
}, record, {
|
||||
w: 1,
|
||||
upsert: true,
|
||||
}, cb);
|
||||
};
|
||||
|
||||
Storage.prototype.fetchCacheData = function(walletId, key, cb) {
|
||||
var self = this;
|
||||
|
||||
self.db.collection(collections.CACHE).findOne({
|
||||
walletId: walletId,
|
||||
key: key,
|
||||
}, function(err, result) {
|
||||
if (err) return cb(err);
|
||||
if (!result) return cb();
|
||||
|
||||
return cb(null, result.data);
|
||||
});
|
||||
};
|
||||
|
||||
Storage.prototype._dump = function(cb, fn) {
|
||||
fn = fn || console.log;
|
||||
cb = cb || function() {};
|
||||
|
|
|
@ -211,52 +211,77 @@ helpers.toSatoshi = function(btc) {
|
|||
}
|
||||
};
|
||||
|
||||
helpers.stubUtxos = function(server, wallet, amounts, cb) {
|
||||
async.mapSeries(_.range(0, amounts.length > 2 ? 2 : 1), function(i, next) {
|
||||
server.createAddress({}, next);
|
||||
}, function(err, addresses) {
|
||||
should.not.exist(err);
|
||||
addresses.should.not.be.empty;
|
||||
var utxos = _.compact(_.map([].concat(amounts), function(amount, i) {
|
||||
var confirmations;
|
||||
if (_.isString(amount) && _.startsWith(amount, 'u')) {
|
||||
amount = parseFloat(amount.substring(1));
|
||||
confirmations = 0;
|
||||
helpers.stubUtxos = function(server, wallet, amounts, opts, cb) {
|
||||
if (_.isFunction(opts)) {
|
||||
cb = opts;
|
||||
opts = {};
|
||||
}
|
||||
opts = opts || {};
|
||||
|
||||
if (!helpers._utxos) helpers._utxos = {};
|
||||
|
||||
async.waterfall([
|
||||
|
||||
function(next) {
|
||||
if (opts.addresses) return next(null, [].concat(opts.addresses));
|
||||
async.mapSeries(_.range(0, amounts.length > 2 ? 2 : 1), function(i, next) {
|
||||
server.createAddress({}, next);
|
||||
}, next);
|
||||
},
|
||||
function(addresses, next) {
|
||||
addresses.should.not.be.empty;
|
||||
|
||||
var utxos = _.compact(_.map([].concat(amounts), function(amount, i) {
|
||||
var confirmations;
|
||||
if (_.isString(amount) && _.startsWith(amount, 'u')) {
|
||||
amount = parseFloat(amount.substring(1));
|
||||
confirmations = 0;
|
||||
} else {
|
||||
confirmations = Math.floor(Math.random() * 100 + 1);
|
||||
}
|
||||
if (amount <= 0) return null;
|
||||
|
||||
var address = addresses[i % addresses.length];
|
||||
|
||||
var scriptPubKey;
|
||||
switch (wallet.addressType) {
|
||||
case Constants.SCRIPT_TYPES.P2SH:
|
||||
scriptPubKey = Bitcore.Script.buildMultisigOut(address.publicKeys, wallet.m).toScriptHashOut();
|
||||
break;
|
||||
case Constants.SCRIPT_TYPES.P2PKH:
|
||||
scriptPubKey = Bitcore.Script.buildPublicKeyHashOut(address.address);
|
||||
break;
|
||||
}
|
||||
should.exist(scriptPubKey);
|
||||
|
||||
return {
|
||||
txid: helpers.randomTXID(),
|
||||
vout: Math.floor(Math.random() * 10 + 1),
|
||||
satoshis: helpers.toSatoshi(amount),
|
||||
scriptPubKey: scriptPubKey.toBuffer().toString('hex'),
|
||||
address: address.address,
|
||||
confirmations: confirmations
|
||||
};
|
||||
}));
|
||||
|
||||
if (opts.keepUtxos) {
|
||||
helpers._utxos = helpers._utxos.concat(utxos);
|
||||
} else {
|
||||
confirmations = Math.floor(Math.random() * 100 + 1);
|
||||
helpers._utxos = utxos;
|
||||
}
|
||||
if (amount <= 0) return null;
|
||||
|
||||
var address = addresses[i % addresses.length];
|
||||
|
||||
var scriptPubKey;
|
||||
switch (wallet.addressType) {
|
||||
case Constants.SCRIPT_TYPES.P2SH:
|
||||
scriptPubKey = Bitcore.Script.buildMultisigOut(address.publicKeys, wallet.m).toScriptHashOut();
|
||||
break;
|
||||
case Constants.SCRIPT_TYPES.P2PKH:
|
||||
scriptPubKey = Bitcore.Script.buildPublicKeyHashOut(address.address);
|
||||
break;
|
||||
}
|
||||
should.exist(scriptPubKey);
|
||||
|
||||
return {
|
||||
txid: helpers.randomTXID(),
|
||||
vout: Math.floor(Math.random() * 10 + 1),
|
||||
satoshis: helpers.toSatoshi(amount),
|
||||
scriptPubKey: scriptPubKey.toBuffer().toString('hex'),
|
||||
address: address.address,
|
||||
confirmations: confirmations
|
||||
blockchainExplorer.getUnspentUtxos = function(addresses, cb) {
|
||||
var selected = _.filter(helpers._utxos, function(utxo) {
|
||||
return _.contains(addresses, utxo.address);
|
||||
});
|
||||
return cb(null, selected);
|
||||
};
|
||||
}));
|
||||
blockchainExplorer.getUnspentUtxos = function(addresses, cb) {
|
||||
var selected = _.filter(utxos, function(utxo) {
|
||||
return _.contains(addresses, utxo.address);
|
||||
});
|
||||
return cb(null, selected);
|
||||
};
|
||||
|
||||
return cb(utxos);
|
||||
return next();
|
||||
},
|
||||
], function(err) {
|
||||
should.not.exist(err);
|
||||
return cb(helpers._utxos);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -451,14 +476,14 @@ helpers.createProposalOpts = function(type, outputs, signingKey, moreOpts, input
|
|||
};
|
||||
helpers.createAddresses = function(server, wallet, main, change, cb) {
|
||||
var clock = sinon.useFakeTimers(Date.now(), 'Date');
|
||||
async.map(_.range(main + change), function(i, next) {
|
||||
async.mapSeries(_.range(main + change), function(i, next) {
|
||||
clock.tick(1000);
|
||||
var address = wallet.createAddress(i >= main);
|
||||
server.storage.storeAddressAndWallet(wallet, address, function(err) {
|
||||
next(err, address);
|
||||
});
|
||||
}, function(err, addresses) {
|
||||
if (err) throw new Error('Could not generate addresses');
|
||||
should.not.exist(err);
|
||||
clock.restore();
|
||||
return cb(_.take(addresses, main), _.takeRight(addresses, change));
|
||||
});
|
||||
|
|
|
@ -1504,7 +1504,7 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('#getBalance 2 steps', function() {
|
||||
describe.only('#getBalance 2 steps', function() {
|
||||
var server, wallet;
|
||||
beforeEach(function(done) {
|
||||
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||
|
@ -1536,22 +1536,118 @@ describe('Wallet service', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
it.only('should trigger notification when balance of non-prioritary addresses is updated', function(done) {
|
||||
helpers.stubUtxos(server, wallet, [1, 2], function() {
|
||||
server.getBalance2Steps({}, function(err, balance) {
|
||||
should.not.exist(err);
|
||||
should.exist(balance);
|
||||
balance.totalAmount.should.equal(helpers.toSatoshi(3));
|
||||
|
||||
helpers.stubUtxos(server, wallet, [0.5, 0.6], function() {
|
||||
server.getBalance2Steps({}, function(err, balance) {
|
||||
should.not.exist(err);
|
||||
should.exist(balance);
|
||||
//balance.totalAmount.should.equal(helpers.toSatoshi(1.1));
|
||||
//done();
|
||||
it('should trigger notification when balance of non-prioritary addresses is updated', function(done) {
|
||||
var addresses;
|
||||
|
||||
async.series([
|
||||
|
||||
function(next) {
|
||||
helpers.createAddresses(server, wallet, 4, 0, function(addrs) {
|
||||
addresses = addrs;
|
||||
helpers.stubUtxos(server, wallet, [1, 2], {
|
||||
addresses: _.take(addresses, 2),
|
||||
}, function() {
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getBalance2Steps({}, function(err, balance) {
|
||||
should.not.exist(err);
|
||||
should.exist(balance);
|
||||
balance.totalAmount.should.equal(helpers.toSatoshi(3));
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
helpers.stubUtxos(server, wallet, 0.5, {
|
||||
addresses: addresses[2],
|
||||
keepUtxos: true,
|
||||
}, function() {
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getBalance2Steps({}, function(err, balance) {
|
||||
should.not.exist(err);
|
||||
should.exist(balance);
|
||||
balance.totalAmount.should.equal(helpers.toSatoshi(3));
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
setTimeout(next, 100);
|
||||
},
|
||||
function(next) {
|
||||
server.getNotifications({}, function(err, notifications) {
|
||||
should.not.exist(err);
|
||||
var last = _.last(notifications);
|
||||
last.type.should.equal('BalanceUpdated');
|
||||
var balance = last.data;
|
||||
balance.totalAmount.should.equal(helpers.toSatoshi(3.5));
|
||||
next();
|
||||
});
|
||||
},
|
||||
], function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not trigger notification when only balance of prioritary addresses is updated', function(done) {
|
||||
var addresses;
|
||||
|
||||
async.series([
|
||||
|
||||
function(next) {
|
||||
helpers.createAddresses(server, wallet, 4, 0, function(addrs) {
|
||||
addresses = addrs;
|
||||
helpers.stubUtxos(server, wallet, [1, 2], {
|
||||
addresses: _.take(addresses, 2),
|
||||
}, function() {
|
||||
next();
|
||||
});
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getBalance2Steps({}, function(err, balance) {
|
||||
should.not.exist(err);
|
||||
should.exist(balance);
|
||||
balance.totalAmount.should.equal(helpers.toSatoshi(3));
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
helpers.stubUtxos(server, wallet, 0.5, {
|
||||
addresses: addresses[0],
|
||||
keepUtxos: true,
|
||||
}, function() {
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getBalance2Steps({}, function(err, balance) {
|
||||
should.not.exist(err);
|
||||
should.exist(balance);
|
||||
balance.totalAmount.should.equal(helpers.toSatoshi(3.5));
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
setTimeout(next, 100);
|
||||
},
|
||||
function(next) {
|
||||
server.getNotifications({}, function(err, notifications) {
|
||||
should.not.exist(err);
|
||||
var last = _.last(notifications);
|
||||
last.type.should.not.equal('BalanceUpdated');
|
||||
next();
|
||||
});
|
||||
},
|
||||
], function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue