test passing with notifications

This commit is contained in:
Matias Alejo Garcia 2015-02-11 23:11:30 -03:00
parent 7a4d16f88e
commit d548639334
4 changed files with 79 additions and 34 deletions

View File

@ -5,21 +5,28 @@ var Uuid = require('uuid');
/*
* notifications examples
*
* newCopayer
* newTxProposal
* txProposalAcceptedBy
* txProposalRejectedBy
* txProposalFinallyRejected
* txProposalFinallyAccepted
* newIncommingTransaction
* newOutgoingTransaction
* NewCopayer -
* NewAddress -
* NewTxProposal - (amount)
* TxProposalAcceptedBy - (txProposalId, copayerId)
* TxProposalRejectedBy - (txProposalId, copayerId)
* txProposalFinallyRejected - txProposalId
* txProposalFinallyAccepted - txProposalId
*
* newIncommingTx (amount)
* newOutgoingTx - (txProposalId, txid)
*
* data Examples:
* { amount: 'xxx', address: 'xxx'}
* { txProposalId: 'xxx', copayerId: 'xxx' }
*
* Data is meant to provide only the needed information
* to notify the user
*
*/
function Notification(opts) {
opts = opts || {};
@ -39,4 +46,4 @@ Notification.prototype.fromObj = function(obj) {
return x;
};
module.export = Notification;
module.exports = Notification;

View File

@ -6,6 +6,7 @@ var log = require('npmlog');
log.debug = log.verbose;
var inherits = require('inherits');
var events = require('events');
var nodeutil = require('util');
var Bitcore = require('bitcore');
var PublicKey = Bitcore.PublicKey;
@ -22,6 +23,7 @@ var Wallet = require('./model/wallet');
var Copayer = require('./model/copayer');
var Address = require('./model/address');
var TxProposal = require('./model/txproposal');
var Notification = require('./model/Notification');
var initialized = false;
@ -36,7 +38,7 @@ function CopayServer() {
this.storage = storage;
};
util.inherits(CopayServer, events.EventEmitter);
nodeutil.inherits(CopayServer, events.EventEmitter);
/**
@ -147,19 +149,22 @@ CopayServer.prototype._verifySignature = function(text, signature, pubKey) {
/**
* notify
* _notify
*
* @param type
* @param data
*/
CopayServer.prototype.notify = function(type, data) {
CopayServer.prototype._notify = function(type, data) {
var self = this;
var walletId = self.walletId || data.walletId;
$.checkState(walletId);
var n = new Notification({
type: type,
data: data,
});
this.storage.storeNotification(this.walletId, n, function () {
this.storage.storeNotification(walletId, n, function() {
self.emit(n);
});
};
@ -202,7 +207,9 @@ CopayServer.prototype.joinWallet = function(opts, cb) {
wallet.addCopayer(copayer);
self.storage.storeWalletAndUpdateCopayersLookup(wallet, function(err) {
self.notify('newCopayer');
self._notify('NewCopayer', {
walletId: opts.walletId,
});
return cb(err, copayer.id);
});
});
@ -227,6 +234,7 @@ CopayServer.prototype.createAddress = function(opts, cb) {
self.storage.storeAddressAndWallet(wallet, address, function(err) {
if (err) return cb(err);
self._notify('NewAddress');
return cb(null, address);
});
});
@ -411,17 +419,20 @@ CopayServer.prototype._selectUtxos = function(txp, utxos) {
CopayServer.prototype.createTx = function(opts, cb) {
var self = this;
if (!Utils.checkRequired(opts, ['toAddress', 'amount'])) return cb(new ClientError('Required argument missing'));
if (!Utils.checkRequired(opts, ['toAddress', 'amount']))
return cb(new ClientError('Required argument missing'));
Utils.runLocked(self.walletId, cb, function(cb) {
self.getWallet({}, function(err, wallet) {
if (err) return cb(err);
if (!wallet.isComplete()) return cb(new ClientError('Wallet is not complete'));
if (wallet.isShared() && !Utils.checkRequired(opts, 'proposalSignature')) return cb(new ClientError('Proposal signature is required for shared wallets'));
if (wallet.isShared() && !Utils.checkRequired(opts, 'proposalSignature'))
return cb(new ClientError('Proposal signature is required for shared wallets'));
var copayer = wallet.getCopayer(self.copayerId);
var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message;
if (!self._verifySignature(msg, opts.proposalSignature, copayer.signingPubKey)) return cb(new ClientError('Invalid proposal signature'));
if (!self._verifySignature(msg, opts.proposalSignature, copayer.signingPubKey))
return cb(new ClientError('Invalid proposal signature'));
var toAddress;
try {
@ -429,7 +440,8 @@ CopayServer.prototype.createTx = function(opts, cb) {
} catch (ex) {
return cb(new ClientError('INVALIDADDRESS', 'Invalid address'));
}
if (toAddress.network != wallet.getNetworkName()) return cb(new ClientError('INVALIDADDRESS', 'Incorrect address network'));
if (toAddress.network != wallet.getNetworkName())
return cb(new ClientError('INVALIDADDRESS', 'Incorrect address network'));
self._getUtxos(function(err, utxos) {
if (err) return cb(err);
@ -463,6 +475,9 @@ CopayServer.prototype.createTx = function(opts, cb) {
self.storage.storeTx(wallet.id, txp, function(err) {
if (err) return cb(err);
self._notify('NewTxProposal', {
amount: opts.amount
});
return cb(null, txp);
});
});
@ -538,6 +553,7 @@ CopayServer.prototype.removePendingTx = function(opts, cb) {
if (actors.length == 1 && actors[0] !== self.copayerId)
return cb(new ClientError('Not allowed to erase this TX'));
self._notify('transactionProposalRemoved');
self.storage.removeTx(self.walletId, opts.id, cb);
});
});
@ -590,7 +606,17 @@ CopayServer.prototype.signTx = function(opts, cb) {
self.storage.storeTx(self.walletId, txp, function(err) {
if (err) return cb(err);
self._notify('TxProposalAcceptedBy', {
txProposalId: opts.txProposalId,
copayerId: self.copayerId,
});
if (txp.status == 'accepted') {
self._notify('TxProposalFinallyAccepted', {
txProposalId: opts.txProposalId,
});
self._broadcastTx(txp, function(err, txid) {
if (err) return cb(err);
@ -598,6 +624,11 @@ CopayServer.prototype.signTx = function(opts, cb) {
self.storage.storeTx(self.walletId, txp, function(err) {
if (err) return cb(err);
self._notify('newOutgoingTx', {
txProposalId: opts.txProposalId,
txid: txid
});
return cb(null, txp);
});
});
@ -628,14 +659,29 @@ CopayServer.prototype.rejectTx = function(opts, cb) {
var action = _.find(txp.actions, {
copayerId: self.copayerId
});
if (action) return cb(new ClientError('CVOTED', 'Copayer already voted on this transaction proposal'));
if (txp.status != 'pending') return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending'));
if (action)
return cb(new ClientError('CVOTED', 'Copayer already voted on this transaction proposal'));
if (txp.status != 'pending')
return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending'));
txp.reject(self.copayerId);
self.storage.storeTx(self.walletId, txp, function(err) {
if (err) return cb(err);
self._notify('TxProposalRejectedBy', {
txProposalId: opts.txProposalId,
copayerId: self.copayerId,
});
if (txp.status == 'rejected') {
self._notify('TxProposalFinallyRejected', {
txProposalId: opts.txProposalId,
});
};
return cb();
});
});

View File

@ -311,6 +311,9 @@ Storage.prototype._removeCopayers = function(walletId, cb) {
});
};
Storage.prototype._removeAllNotifications = function(walletId, cb) {
this._delByKey(KEY.NOTIFICATION(walletId), cb);
};
Storage.prototype._removeAllAddresses = function(walletId, cb) {
@ -323,23 +326,11 @@ Storage.prototype.removeWallet = function(walletId, cb) {
async.series([
function(next) {
// This should be the first step. Will check the wallet exists
self._removeCopayers(walletId, next);
},
function(next) {
self._removeAllAddresses(walletId, next);
},
function(next) {
self.removeAllPendingTxs(walletId, next);
},
function(next) {
self.removeAllTxs(walletId, next);
},
function(next) {
var ops = [{
type: 'del',
key: KEY.WALLET(walletId),
}];
self.db.batch(ops, next);
self._delByKey(walletPrefix(walletId), cb);
},
], cb);
};

View File

@ -1202,6 +1202,7 @@ describe('Copay server', function() {
server.removeWallet({}, function(err) {
i = 0;
server.storage._dump(function() {
server.storage._dump();
i.should.equal(0);
done();
}, count);