add wallet.id to debug logs

This commit is contained in:
Matias Alejo Garcia 2014-10-07 18:33:55 -03:00
commit 622c3da68c
10 changed files with 299 additions and 160 deletions

View file

@ -44,11 +44,9 @@ angular.module('copayApp.controllers').controller('CreateController',
networkName: $scope.networkName, networkName: $scope.networkName,
}; };
$rootScope.iden.createWallet(opts, function(err, w) { $rootScope.iden.createWallet(opts, function(err, w) {
$rootScope.iden.closeWallet($rootScope.wallet.id, function() { $scope.loading = false;
$scope.loading = false; $rootScope.wallet = w;
$rootScope.wallet = w; controllerUtils.bindWallet(w, $scope);
controllerUtils.bindWallet(w, $scope);
});
}); });
}; };
}); });

View file

@ -139,11 +139,9 @@ angular.module('copayApp.controllers').controller('JoinController',
notification.error('Unknown error'); notification.error('Unknown error');
controllerUtils.onErrorDigest(); controllerUtils.onErrorDigest();
} else { } else {
$rootScope.iden.closeWallet($rootScope.wallet.id, function() { $scope.loading = false;
$scope.loading = false; $rootScope.wallet = w;
$rootScope.wallet = w; controllerUtils.bindWallet(w, $scope);
controllerUtils.bindWallet(w, $scope);
});
} }
}); });
} }

View file

@ -19,15 +19,16 @@ function Network(opts) {
this.secretNumber = opts.secretNumber; this.secretNumber = opts.secretNumber;
this.cleanUp(); this.cleanUp();
this.socketOptions = { this.socketOptions = {
reconnection: true, reconnection: true,
'force new connection': true, 'force new connection': true,
'secure': this.url.indexOf('https') === 0, 'secure': this.url.indexOf('https') === 0,
}; };
if (opts.transports) { if (opts.transports) {
this.socketOptions['transports'] = opts.transports; this.socketOptions['transports'] = opts.transports;
} }
this.socket = this.createSocket();
} }
nodeUtil.inherits(Network, EventEmitter); nodeUtil.inherits(Network, EventEmitter);
@ -262,9 +263,11 @@ Network.prototype._setupConnectionHandlers = function(opts, cb) {
self.socket.on('no messages', self.emit.bind(self, 'no messages')); self.socket.on('no messages', self.emit.bind(self, 'no messages'));
var pubkey = self.getKey().public.toString('hex');
self.socket.on('connect', function() { self.socket.on('connect', function() {
var pubkey = self.getKey().public.toString('hex'); var pubkey = self.getKey().public.toString('hex');
log.debug('Async subscribing to:pubkey:',pubkey); log.debug('Async subscribing to pubkey:', pubkey);
self.socket.emit('subscribe', pubkey); self.socket.emit('subscribe', pubkey);
@ -322,7 +325,6 @@ Network.prototype.start = function(opts, openCallback) {
preconditions.checkArgument(opts); preconditions.checkArgument(opts);
preconditions.checkArgument(opts.privkey); preconditions.checkArgument(opts.privkey);
preconditions.checkArgument(opts.copayerId); preconditions.checkArgument(opts.copayerId);
preconditions.checkState(this.connectedPeers && this.connectedPeers.length === 0); preconditions.checkState(this.connectedPeers && this.connectedPeers.length === 0);
if (this.started) { if (this.started) {
@ -333,8 +335,6 @@ Network.prototype.start = function(opts, openCallback) {
this.privkey = opts.privkey; this.privkey = opts.privkey;
this.setCopayerId(opts.copayerId); this.setCopayerId(opts.copayerId);
this.maxPeers = opts.maxPeers || this.maxPeers; this.maxPeers = opts.maxPeers || this.maxPeers;
this.socket = this.createSocket();
this._setupConnectionHandlers(opts, openCallback); this._setupConnectionHandlers(opts, openCallback);
}; };

View file

@ -46,13 +46,13 @@ function Identity(email, password, opts) {
this.storage = Identity._newStorage(storageOpts); this.storage = Identity._newStorage(storageOpts);
this.storage.setPassword(password); this.storage.setPassword(password);
this.networks = { this.networkOpts = {
'livenet': Identity._newAsync(opts.network.livenet), 'livenet': opts.network.livenet,
'testnet': Identity._newAsync(opts.network.testnet), 'testnet': opts.network.testnet,
}; };
this.blockchains = { this.blockchainOpts = {
'livenet': Identity._newInsight(opts.network.livenet), 'livenet': opts.network.livenet,
'testnet': Identity._newInsight(opts.network.testnet), 'testnet': opts.network.testnet,
}; };
this.walletDefaults = opts.walletDefaults || {}; this.walletDefaults = opts.walletDefaults || {};
@ -68,14 +68,6 @@ Identity._createProfile = function(email, password, storage, cb) {
Profile.create(email, password, storage, cb); Profile.create(email, password, storage, cb);
}; };
Identity._newInsight = function(opts) {
return new Insight(opts);
};
Identity._newAsync = function(opts) {
return new Async(opts);
};
Identity._newStorage = function(opts) { Identity._newStorage = function(opts) {
@ -90,8 +82,8 @@ Identity._walletFromObj = function(o, s, n, b, skip) {
return Wallet.fromObj(o, s, n, b, skip); return Wallet.fromObj(o, s, n, b, skip);
}; };
Identity._walletRead = function(id, s, n, b, skip, cb) { Identity._walletRead = function(id, r, cb) {
return Wallet.read(id, s, n, b, skip, cb); return Wallet.read(id, r, cb);
}; };
Identity._walletDelete = function(id, s, cb) { Identity._walletDelete = function(id, s, cb) {
@ -103,6 +95,12 @@ Identity._openProfile = function(email, password, storage, cb) {
Profile.open(email, password, storage, cb); Profile.open(email, password, storage, cb);
}; };
/* for stubbing */
Identity._newAsync = function(opts) {
return new Async(opts);
};
/** /**
@ -237,13 +235,7 @@ Identity.prototype.store = function(opts, cb) {
Identity.prototype._cleanUp = function() { Identity.prototype._cleanUp = function() {
log.info('Cleaning Network connections') // NOP
var self = this;
_.each(['livenet', 'testnet'], function(n) {
self.networks[n].cleanUp();
self.blockchains[n].destroy();
});
}; };
/** /**
@ -261,10 +253,8 @@ Identity.prototype.close = function(cb) {
var self = this; var self = this;
_.each(this.openWallets, function(w) { _.each(this.openWallets, function(w) {
w.close(function(err) { w.close(function(err) {
console.log('[Identity.js.239:err:]', err); //TODO
if (err) return cb(err); if (err) return cb(err);
console.log('[Identity.js.241]', i, l); //TODO
if (++i == l) { if (++i == l) {
self._cleanUp(); self._cleanUp();
if (cb) return cb(); if (cb) return cb();
@ -289,8 +279,7 @@ Identity.prototype.importWallet = function(base64, password, skipFields, cb) {
var obj = this.storage.decrypt(base64); var obj = this.storage.decrypt(base64);
if (!obj) return false; if (!obj) return false;
var networkName = Wallet.obtainNetworkName(obj); var w = Identity._walletFromObj(obj, this.storage, this.networkOpts, this.blockchainOpts);
var w = Identity._walletFromObj(obj, this.storage, this.networks[networkName], this.blockchains[networkName]);
this._checkVersion(w.version); this._checkVersion(w.version);
this.addWallet(w, function(err) { this.addWallet(w, function(err) {
if (err) return cb(err); if (err) return cb(err);
@ -374,8 +363,8 @@ Identity.prototype.createWallet = function(opts, cb) {
opts.storage = this.storage; opts.storage = this.storage;
opts.network = this.networks[opts.networkName]; opts.networkOpts = this.networkOpts;
opts.blockchain = this.blockchains[opts.networkName]; opts.blockchainOpts = this.blockchainOpts;
opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed; opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed;
opts.reconnectDelay = opts.reconnectDelay || this.walletDefaults.reconnectDelay; opts.reconnectDelay = opts.reconnectDelay || this.walletDefaults.reconnectDelay;
@ -383,7 +372,7 @@ Identity.prototype.createWallet = function(opts, cb) {
opts.totalCopayers = totalCopayers; opts.totalCopayers = totalCopayers;
opts.version = opts.version || this.version; opts.version = opts.version || this.version;
if (opts.password) if (opts.password && !this.storage.hasPassphrase())
this.storage.setPassword(opts.password); this.storage.setPassword(opts.password);
var self = this; var self = this;
@ -393,6 +382,7 @@ Identity.prototype.createWallet = function(opts, cb) {
self.openWallets.push(w); self.openWallets.push(w);
self.profile.setLastOpenedTs(w.id, function(err) { self.profile.setLastOpenedTs(w.id, function(err) {
w.netStart();
return cb(err, w); return cb(err, w);
}); });
}); });
@ -451,13 +441,18 @@ Identity.prototype.openWallet = function(walletId, password, cb) {
preconditions.checkArgument(cb); preconditions.checkArgument(cb);
var self = this; var self = this;
if (password) if (password && !this.storage.hasPassphrase())
self.storage.setPassword(password); self.storage.setPassword(password);
// TODO // TODO
// self.migrateWallet(walletId, password, function() { // self.migrateWallet(walletId, password, function() {
//
Identity._walletRead(walletId, self.storage, self.networks, self.blockchains, [], function(err, w) { Identity._walletRead(walletId, {
storage: self.storage,
networkOpts: this.networkOpts,
blockchainOpts: this.blockchainOpts
}, function(err, w) {
if (err) return cb(err); if (err) return cb(err);
self.openWallets.push(w); self.openWallets.push(w);
@ -552,8 +547,8 @@ Identity.prototype.joinWallet = function(opts, cb) {
secretNumber: decodedSecret.secretNumber, secretNumber: decodedSecret.secretNumber,
}; };
var joinNetwork = this.networks[decodedSecret.networkName];
joinNetwork.cleanUp(); var joinNetwork = Identity._newAsync(this.networkOpts[decodedSecret.networkName]);
// This is a hack to reconize if the connection was rejected or the peer wasn't there. // This is a hack to reconize if the connection was rejected or the peer wasn't there.
var connectedOnce = false; var connectedOnce = false;
@ -569,6 +564,7 @@ Identity.prototype.joinWallet = function(opts, cb) {
return cb('joinError'); return cb('joinError');
}); });
console.log('[Identity.js.566:joinOpts:]',joinOpts); //TODO
joinNetwork.start(joinOpts, function() { joinNetwork.start(joinOpts, function() {
joinNetwork.greet(decodedSecret.pubKey, joinOpts.secretNumber); joinNetwork.greet(decodedSecret.pubKey, joinOpts.secretNumber);
@ -589,7 +585,6 @@ Identity.prototype.joinWallet = function(opts, cb) {
walletOpts.password = opts.password; walletOpts.password = opts.password;
self.createWallet(walletOpts, function(err, w) { self.createWallet(walletOpts, function(err, w) {
if (w) { if (w) {
w.sendWalletReady(decodedSecret.pubKey); w.sendWalletReady(decodedSecret.pubKey);
} else { } else {

View file

@ -203,7 +203,6 @@ Insight.prototype.subscribe = function(addresses) {
return function(txid) { return function(txid) {
// verify the address is still subscribed // verify the address is still subscribed
if (!self.subscribed[address]) return; if (!self.subscribed[address]) return;
log.debug('insight tx event');
self.emit('tx', { self.emit('tx', {
address: address, address: address,

View file

@ -2,7 +2,6 @@
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var _ = require('underscore'); var _ = require('underscore');
var async = require('async');
var preconditions = require('preconditions').singleton(); var preconditions = require('preconditions').singleton();
var inherits = require('inherits'); var inherits = require('inherits');
var events = require('events'); var events = require('events');
@ -25,6 +24,8 @@ var TxProposal = require('./TxProposal');
var TxProposals = require('./TxProposals'); var TxProposals = require('./TxProposals');
var PrivateKey = require('./PrivateKey'); var PrivateKey = require('./PrivateKey');
var WalletLock = require('./WalletLock'); var WalletLock = require('./WalletLock');
var Async = require('./Async');
var Insight = module.exports.Insight = require('./Insight');
var copayConfig = require('../../config'); var copayConfig = require('../../config');
/** /**
@ -61,6 +62,12 @@ function Wallet(opts) {
opts.reconnectDelay = opts.reconnectDelay || 500; opts.reconnectDelay = opts.reconnectDelay || 500;
var networkName = Wallet.obtainNetworkName(opts);
preconditions.checkState( (opts.network && opts.blockchain) || networkName);
opts.network = opts.network || Wallet._newAsync(opts.networkOpts[networkName]);
opts.blockchain = opts.blockchain || Wallet._newInsight(opts.blockchainOpts[networkName]);;
//required params //required params
['storage', 'network', 'blockchain', ['storage', 'network', 'blockchain',
'requiredCopayers', 'totalCopayers', 'spendUnconfirmed', 'requiredCopayers', 'totalCopayers', 'spendUnconfirmed',
@ -83,7 +90,7 @@ function Wallet(opts) {
this.registeredPeerIds = []; this.registeredPeerIds = [];
this.addressBook = opts.addressBook || {}; this.addressBook = opts.addressBook || {};
this.publicKey = this.privateKey.publicHex; this.publicKey = this.privateKey.publicHex;
this.lastTimestamp = opts.lastTimestamp || undefined; this.lastTimestamp = opts.lastTimestamp || 0;
this.lastMessageFrom = {}; this.lastMessageFrom = {};
//to avoid confirmation of copayer's backups if is imported from a file //to avoid confirmation of copayer's backups if is imported from a file
@ -96,8 +103,6 @@ function Wallet(opts) {
this.paymentRequests = opts.paymentRequests || {}; this.paymentRequests = opts.paymentRequests || {};
var networkName = Wallet.obtainNetworkName(opts); var networkName = Wallet.obtainNetworkName(opts);
this.network = networkName && this.network[networkName] ? this.network[networkName] : this.network;
this.blockchain = networkName && this.blockchain[networkName] ? this.blockchain[networkName] : this.blockchain;
preconditions.checkArgument(this.network.setHexNonce, 'Incorrect network parameter'); preconditions.checkArgument(this.network.setHexNonce, 'Incorrect network parameter');
preconditions.checkArgument(this.blockchain.getTransaction, 'Incorrect blockchain parameter'); preconditions.checkArgument(this.blockchain.getTransaction, 'Incorrect blockchain parameter');
@ -160,6 +165,16 @@ Wallet.COPAYER_PAIR_LIMITS = {
12: 1, 12: 1,
}; };
/* for stubbing */
Wallet._newInsight = function(opts) {
return new Insight(opts);
};
/* for stubbing */
Wallet._newAsync = function(opts) {
return new Async(opts);
};
/** /**
* @desc Retrieve a random id for the wallet * @desc Retrieve a random id for the wallet
* @TODO: Discuss changing to a UUID * @TODO: Discuss changing to a UUID
@ -213,16 +228,17 @@ Wallet.delete = function(walletId, storage, cb) {
* @desc Retrieve a wallet from storage * @desc Retrieve a wallet from storage
* *
* @param {string} walletId - the wallet id * @param {string} walletId - the wallet id
* @param storage * @param readOpts (see fromObj)
* @param network
* @param blockchain
* @param {string[]} skipFields - parameters to ignore when importing
* @param {function} callback - {err, Wallet} * @param {function} callback - {err, Wallet}
* @return {undefined} * @return {undefined}
*/ */
Wallet.read = function(walletId, storage, network, blockchain, skipFields, cb) { Wallet.read = function(walletId, readOpts, cb) {
preconditions.checkArgument(readOpts);
preconditions.checkArgument(readOpts.storage);
preconditions.checkArgument(readOpts.storage.setPassword);
preconditions.checkArgument(cb); preconditions.checkArgument(cb);
preconditions.checkArgument(storage.setPassword);
var storage = readOpts.storage;
var self = this, var self = this,
err; err;
@ -242,7 +258,7 @@ Wallet.read = function(walletId, storage, network, blockchain, skipFields, cb) {
obj.id = walletId; obj.id = walletId;
try { try {
log.debug('## OPENING Wallet: ' + walletId); log.debug('## OPENING Wallet: ' + walletId);
w = self.fromObj(obj, storage, network, blockchain, skipFields); w = self.fromObj(obj, readOpts);
} catch (e) { } catch (e) {
log.debug("ERROR: ", e.message); log.debug("ERROR: ", e.message);
if (e && e.message && e.message.indexOf('MISSOPTS')) { if (e && e.message && e.message.indexOf('MISSOPTS')) {
@ -266,7 +282,7 @@ Wallet.read = function(walletId, storage, network, blockchain, skipFields, cb) {
Wallet.obtainNetworkName = function(obj) { Wallet.obtainNetworkName = function(obj) {
return obj.networkName || return obj.networkName ||
(obj.opts ? obj.opts.networkName : null) || (obj.opts ? obj.opts.networkName : null) ||
(obj.publicKeyRing ? obj.publicKeyRing.networkName : null) || (obj.publicKeyRing ? (obj.publicKeyRing.networkName || obj.publicKeyRing.network.name) : null) ||
(obj.privateKey ? obj.privateKey.networkName : null); (obj.privateKey ? obj.privateKey.networkName : null);
}; };
@ -293,7 +309,7 @@ Wallet.prototype.seedCopayer = function(pubKey) {
* @emits publicKeyRingUpdated * @emits publicKeyRingUpdated
*/ */
Wallet.prototype._onIndexes = function(senderId, data) { Wallet.prototype._onIndexes = function(senderId, data) {
log.debug('RECV INDEXES:', data); log.debug('Wallet:' + this.id + ' RECV INDEXES:', data);
var inIndexes = HDParams.fromList(data.indexes); var inIndexes = HDParams.fromList(data.indexes);
var hasChanged = this.publicKeyRing.mergeIndexes(inIndexes); var hasChanged = this.publicKeyRing.mergeIndexes(inIndexes);
if (hasChanged) { if (hasChanged) {
@ -339,7 +355,7 @@ Wallet.prototype.changeSettings = function(settings) {
* @emits connectionError * @emits connectionError
*/ */
Wallet.prototype._onPublicKeyRing = function(senderId, data) { Wallet.prototype._onPublicKeyRing = function(senderId, data) {
log.debug('RECV PUBLICKEYRING:', data); log.debug('Wallet:' + this.id +' RECV PUBLICKEYRING:', data);
var inPKR = PublicKeyRing.fromObj(data.publicKeyRing); var inPKR = PublicKeyRing.fromObj(data.publicKeyRing);
var wasIncomplete = !this.publicKeyRing.isComplete(); var wasIncomplete = !this.publicKeyRing.isComplete();
@ -348,7 +364,7 @@ Wallet.prototype._onPublicKeyRing = function(senderId, data) {
try { try {
hasChanged = this.publicKeyRing.merge(inPKR, true); hasChanged = this.publicKeyRing.merge(inPKR, true);
} catch (e) { } catch (e) {
log.debug('## WALLET ERROR', e); log.debug('Wallet:' + this.id +'## WALLET ERROR', e);
this.emit('connectionError', e.message); this.emit('connectionError', e.message);
return; return;
} }
@ -477,7 +493,7 @@ Wallet.prototype._checkSentTx = function(ntxid, cb) {
*/ */
Wallet.prototype._onTxProposal = function(senderId, data) { Wallet.prototype._onTxProposal = function(senderId, data) {
var self = this; var self = this;
log.debug('RECV TXPROPOSAL: ', data); log.debug('Wallet:' + this.id +' RECV TXPROPOSAL: ', data);
var m; var m;
try { try {
@ -530,7 +546,7 @@ Wallet.prototype._onTxProposal = function(senderId, data) {
*/ */
Wallet.prototype._onReject = function(senderId, data) { Wallet.prototype._onReject = function(senderId, data) {
preconditions.checkState(data.ntxid); preconditions.checkState(data.ntxid);
log.debug('RECV REJECT:', data); log.debug('Wallet:' + this.id +' RECV REJECT:', data);
var txp = this.txProposals.get(data.ntxid); var txp = this.txProposals.get(data.ntxid);
@ -563,7 +579,7 @@ Wallet.prototype._onReject = function(senderId, data) {
*/ */
Wallet.prototype._onSeen = function(senderId, data) { Wallet.prototype._onSeen = function(senderId, data) {
preconditions.checkState(data.ntxid); preconditions.checkState(data.ntxid);
log.debug('RECV SEEN:', data); log.debug('Wallet:' + this.id +' RECV SEEN:', data);
var txp = this.txProposals.get(data.ntxid); var txp = this.txProposals.get(data.ntxid);
txp.setSeen(senderId); txp.setSeen(senderId);
@ -591,7 +607,7 @@ Wallet.prototype._onSeen = function(senderId, data) {
*/ */
Wallet.prototype._onAddressBook = function(senderId, data) { Wallet.prototype._onAddressBook = function(senderId, data) {
preconditions.checkState(data.addressBook); preconditions.checkState(data.addressBook);
log.debug('RECV ADDRESSBOOK:', data); log.debug('Wallet:' + this.id +' RECV ADDRESSBOOK:', data);
var rcv = data.addressBook; var rcv = data.addressBook;
var hasChange; var hasChange;
for (var key in rcv) { for (var key in rcv) {
@ -617,7 +633,7 @@ Wallet.prototype.updateTimestamp = function(ts) {
preconditions.checkArgument(ts); preconditions.checkArgument(ts);
preconditions.checkArgument(_.isNumber(ts)); preconditions.checkArgument(_.isNumber(ts));
this.lastTimestamp = ts; this.lastTimestamp = ts;
this.store(); // we dont store here
}; };
/** /**
@ -625,8 +641,9 @@ Wallet.prototype.updateTimestamp = function(ts) {
* Triggers a call to {@link Wallet#sendWalletReady} * Triggers a call to {@link Wallet#sendWalletReady}
*/ */
Wallet.prototype._onNoMessages = function() { Wallet.prototype._onNoMessages = function() {
log.debug('No messages at the server. Requesting peer sync from: ' + this.lastTimestamp + 1); //TODO log.debug('Wallet:' + this.id +' No messages at the server. Requesting peer sync from: ' + (this.lastTimestamp + 1));
this.sendWalletReady(null, parseInt((this.lastTimestamp + 1) / 1000)); this.sendWalletReady(null, parseInt((this.lastTimestamp + 1) / 1000));
this.updateTimestamp(parseInt(Date.now() / 1000));
}; };
/** /**
@ -644,14 +661,18 @@ Wallet.prototype._onData = function(senderId, data, ts) {
preconditions.checkArgument(data.type); preconditions.checkArgument(data.type);
preconditions.checkArgument(ts); preconditions.checkArgument(ts);
preconditions.checkArgument(_.isNumber(ts)); preconditions.checkArgument(_.isNumber(ts));
log.debug('RECV', senderId, data); log.debug('Wallet:' + this.id +' RECV', senderId, data);
console.log('[Wallet.js.635]'); //TODO
this.updateTimestamp(ts);
console.log('[Wallet.js.638]'); //TODO
if (data.type !== 'walletId' && this.id !== data.walletId) { if (data.type !== 'walletId' && this.id !== data.walletId) {
log.debug('Received corrupt message:', data) log.debug('Wallet:' + this.id +' Received corrupt message:', data)
this.emit('corrupt', senderId); this.emit('corrupt', senderId);
this.updateTimestamp(ts);
return; return;
} }
console.log('[Wallet.js.644]'); //TODO
switch (data.type) { switch (data.type) {
// This handler is repeaded on WalletFactory (#join). TODO // This handler is repeaded on WalletFactory (#join). TODO
@ -659,8 +680,12 @@ Wallet.prototype._onData = function(senderId, data, ts) {
this.sendWalletReady(senderId); this.sendWalletReady(senderId);
break; break;
case 'walletReady': case 'walletReady':
console.log('[Wallet.js.653]', this.lastMessageFrom[senderId] ); //TODO
if (this.lastMessageFrom[senderId] !== 'walletReady') { if (this.lastMessageFrom[senderId] !== 'walletReady') {
log.debug('peer Sync received. since: ' + (data.sinceTs || 0));
console.log('[Wallet.js.656]'); //TODO
log.debug('Wallet:' + this.id +' peer Sync received. since: ' + (data.sinceTs || 0));
this.sendPublicKeyRing(senderId); this.sendPublicKeyRing(senderId);
this.sendAddressBook(senderId); this.sendAddressBook(senderId);
this.sendAllTxProposals(senderId, data.sinceTs); // send old txps this.sendAllTxProposals(senderId, data.sinceTs); // send old txps
@ -691,9 +716,8 @@ Wallet.prototype._onData = function(senderId, data, ts) {
default: default:
throw new Error('unknown message type received: ' + data.type + ' from: ' + senderId) throw new Error('unknown message type received: ' + data.type + ' from: ' + senderId)
} }
this.lastMessageFrom[senderId] = data.type; this.lastMessageFrom[senderId] = data.type;
this.updateTimestamp(ts);
}; };
/** /**
@ -703,10 +727,11 @@ Wallet.prototype._onData = function(senderId, data, ts) {
*/ */
Wallet.prototype._onConnect = function(newCopayerId) { Wallet.prototype._onConnect = function(newCopayerId) {
if (newCopayerId) { if (newCopayerId) {
log.debug('#### Setting new COPAYER:', newCopayerId); log.debug('Wallet:' + this.id +'#### Setting new COPAYER:', newCopayerId);
this.sendWalletId(newCopayerId); this.sendWalletId(newCopayerId);
} }
var peerID = this.network.peerFromCopayer(newCopayerId)
var peerID = this.network.peerFromCopayer(newCopayerId);
this.emit('connect', peerID); this.emit('connect', peerID);
}; };
@ -828,16 +853,16 @@ Wallet.prototype._setBlockchainListeners = function() {
this.blockchain.removeAllListeners(); this.blockchain.removeAllListeners();
this.blockchain.on('reconnect', function(attempts) { this.blockchain.on('reconnect', function(attempts) {
log.debug('blockchain reconnect event'); log.debug('Wallet:' + this.id +'blockchain reconnect event');
self.emit('insightReconnected'); self.emit('insightReconnected');
}); });
this.blockchain.on('disconnect', function() { this.blockchain.on('disconnect', function() {
log.debug('blockchain disconnect event'); log.debug('Wallet:' + this.id +'blockchain disconnect event');
self.emit('insightError'); self.emit('insightError');
}); });
this.blockchain.on('tx', function(tx) { this.blockchain.on('tx', function(tx) {
log.debug('blockchain tx event'); log.debug('Wallet:' + this.id +'blockchain tx event');
var addresses = self.getAddressesInfo(); var addresses = self.getAddressesInfo();
var addr = _.findWhere(addresses, { var addr = _.findWhere(addresses, {
addressStr: tx.address addressStr: tx.address
@ -870,7 +895,7 @@ Wallet.prototype.netStart = function() {
var net = this.network; var net = this.network;
if (net.started) { if (net.started) {
log.debug('Wallet networking was ready') log.debug('Wallet:' + self.id +' Wallet networking was ready')
self.emit('ready', net.getPeer()); self.emit('ready', net.getPeer());
return; return;
} }
@ -899,9 +924,9 @@ Wallet.prototype.netStart = function() {
self.emit('connectionError'); self.emit('connectionError');
}); });
log.debug('Wallet: Starting networking'); log.debug('Wallet:' + self.id + ' Starting networking: ' + startOpts.copayerId);
net.start(startOpts, function() { net.start(startOpts, function() {
log.debug('Wallet: Networking ready'); log.debug('Wallet:' + self.id + ' Networking ready:', net.copayerId);
self._setBlockchainListeners(); self._setBlockchainListeners();
self.emit('ready', net.getPeer()); self.emit('ready', net.getPeer());
setTimeout(function() { setTimeout(function() {
@ -979,7 +1004,7 @@ Wallet.prototype.store = function(cb) {
var val = this.toObj(); var val = this.toObj();
var key = 'wallet::' + this.id + ((val.opts && val.opts.name) ? '_' + val.opts.name : ''); var key = 'wallet::' + this.id + ((val.opts && val.opts.name) ? '_' + val.opts.name : '');
this.storage.set(key, val, function(err) { this.storage.set(key, val, function(err) {
log.debug('Wallet stored'); log.debug('Wallet:' + self.id +' stored');
if (cb) if (cb)
cb(err); cb(err);
}); });
@ -1023,12 +1048,22 @@ Wallet.prototype.toObj = function() {
* @param {number} o.lastTimestamp - last time this wallet object was deserialized * @param {number} o.lastTimestamp - last time this wallet object was deserialized
* @param {Object} o.txProposals - TxProposals to be deserialized by {@link TxProposals#fromObj} * @param {Object} o.txProposals - TxProposals to be deserialized by {@link TxProposals#fromObj}
* @param {string} o.nickname - user's nickname * @param {string} o.nickname - user's nickname
* @param {Storage} storage - a Storage instance to store the data of the wallet * @param readOpts.storage
* @param {Network} network - a Network instance to communicate with peers * @param readOpts.network
* @param {Blockchain} blockchain - a Blockchain instance to retrieve state from the blockchain * @param readOpts.blockchain
* @param skipFields * @param readOpts.{string[]} skipFields - parameters to ignore when importing
*/ */
Wallet.fromObj = function(o, storage, network, blockchain, skipFields) { Wallet.fromObj = function(o, readOpts) {
preconditions.checkArgument(readOpts.networkOpts);
preconditions.checkArgument(readOpts.blockchainOpts);
preconditions.checkArgument(readOpts.storage.setPassword);
var storage = readOpts.storage;
var networkOpts = readOpts.networkOpts;
var blockchainOpts = readOpts.blockchainOpts;
var skipFields = readOpts.skipFields || [];
if (skipFields) { if (skipFields) {
_.each(skipFields, function(k) { _.each(skipFields, function(k) {
@ -1085,9 +1120,9 @@ Wallet.fromObj = function(o, storage, network, blockchain, skipFields) {
opts.lastTimestamp = o.lastTimestamp || 0; opts.lastTimestamp = o.lastTimestamp || 0;
opts.storage = storage; opts.storage = storage;
opts.network = network;
opts.blockchain = blockchain;
opts.isImported = true; opts.isImported = true;
opts.blockchainOpts = readOpts.blockchainOpts;
opts.networkOpts = readOpts.networkOpts;
return new Wallet(opts); return new Wallet(opts);
}; };
@ -1129,7 +1164,7 @@ Wallet.prototype.sendAllTxProposals = function(recipients, sinceTs) {
*/ */
Wallet.prototype.sendTxProposal = function(ntxid, recipients) { Wallet.prototype.sendTxProposal = function(ntxid, recipients) {
preconditions.checkArgument(ntxid); preconditions.checkArgument(ntxid);
log.debug('### SENDING txProposal ' + ntxid + ' TO:', recipients || 'All', this.txProposals); log.debug('Wallet:' + this.id +' ### SENDING txProposal ' + ntxid + ' TO:', recipients || 'All', this.txProposals);
this.send(recipients, { this.send(recipients, {
type: 'txProposal', type: 'txProposal',
txProposal: this.txProposals.get(ntxid).toObjTrim(), txProposal: this.txProposals.get(ntxid).toObjTrim(),
@ -1143,7 +1178,7 @@ Wallet.prototype.sendTxProposal = function(ntxid, recipients) {
*/ */
Wallet.prototype.sendSeen = function(ntxid) { Wallet.prototype.sendSeen = function(ntxid) {
preconditions.checkArgument(ntxid); preconditions.checkArgument(ntxid);
log.debug('### SENDING seen: ' + ntxid + ' TO: All'); log.debug('Wallet:' + this.id +' ### SENDING seen: ' + ntxid + ' TO: All');
this.send(null, { this.send(null, {
type: 'seen', type: 'seen',
ntxid: ntxid, ntxid: ntxid,
@ -1157,7 +1192,7 @@ Wallet.prototype.sendSeen = function(ntxid) {
*/ */
Wallet.prototype.sendReject = function(ntxid) { Wallet.prototype.sendReject = function(ntxid) {
preconditions.checkArgument(ntxid); preconditions.checkArgument(ntxid);
log.debug('### SENDING reject: ' + ntxid + ' TO: All'); log.debug('Wallet:' + this.id +' ### SENDING reject: ' + ntxid + ' TO: All');
this.send(null, { this.send(null, {
type: 'reject', type: 'reject',
ntxid: ntxid, ntxid: ntxid,
@ -1170,7 +1205,7 @@ Wallet.prototype.sendReject = function(ntxid) {
* @param {string[]} [recipients] - the pubkeys of the recipients * @param {string[]} [recipients] - the pubkeys of the recipients
*/ */
Wallet.prototype.sendWalletReady = function(recipients, sinceTs) { Wallet.prototype.sendWalletReady = function(recipients, sinceTs) {
log.debug('### SENDING WalletReady TO:', recipients || 'All'); log.debug('Wallet:' + this.id +' ### SENDING WalletReady TO:', recipients || 'All');
this.send(recipients, { this.send(recipients, {
type: 'walletReady', type: 'walletReady',
@ -1185,7 +1220,7 @@ Wallet.prototype.sendWalletReady = function(recipients, sinceTs) {
* @param {string[]} [recipients] - the pubkeys of the recipients * @param {string[]} [recipients] - the pubkeys of the recipients
*/ */
Wallet.prototype.sendWalletId = function(recipients) { Wallet.prototype.sendWalletId = function(recipients) {
log.debug('### SENDING walletId TO:', recipients || 'All', this.id); log.debug('Wallet:' + this.id +' ### SENDING walletId TO:', recipients || 'All', this.id);
this.send(recipients, { this.send(recipients, {
type: 'walletId', type: 'walletId',
@ -1200,7 +1235,7 @@ Wallet.prototype.sendWalletId = function(recipients) {
* @param {string[]} [recipients] - the pubkeys of the recipients * @param {string[]} [recipients] - the pubkeys of the recipients
*/ */
Wallet.prototype.sendPublicKeyRing = function(recipients) { Wallet.prototype.sendPublicKeyRing = function(recipients) {
log.debug('### SENDING publicKeyRing TO:', recipients || 'All', this.publicKeyRing.toObj()); log.debug('Wallet:' + this.id +' ### SENDING publicKeyRing TO:', recipients || 'All', this.publicKeyRing.toObj());
var publicKeyRing = this.publicKeyRing.toObj(); var publicKeyRing = this.publicKeyRing.toObj();
this.send(recipients, { this.send(recipients, {
@ -1216,7 +1251,7 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) {
*/ */
Wallet.prototype.sendIndexes = function(recipients) { Wallet.prototype.sendIndexes = function(recipients) {
var indexes = HDParams.serialize(this.publicKeyRing.indexes); var indexes = HDParams.serialize(this.publicKeyRing.indexes);
log.debug('### INDEXES TO:', recipients || 'All', indexes); log.debug('Wallet:' + this.id +' ### INDEXES TO:', recipients || 'All', indexes);
this.send(recipients, { this.send(recipients, {
type: 'indexes', type: 'indexes',
@ -1230,7 +1265,7 @@ Wallet.prototype.sendIndexes = function(recipients) {
* @param {string[]} recipients - the pubkeys of the recipients * @param {string[]} recipients - the pubkeys of the recipients
*/ */
Wallet.prototype.sendAddressBook = function(recipients) { Wallet.prototype.sendAddressBook = function(recipients) {
log.debug('### SENDING addressBook TO:', recipients || 'All', this.addressBook); log.debug('Wallet:' + this.id +' ### SENDING addressBook TO:', recipients || 'All', this.addressBook);
this.send(recipients, { this.send(recipients, {
type: 'addressbook', type: 'addressbook',
addressBook: this.addressBook, addressBook: this.addressBook,
@ -1391,23 +1426,23 @@ Wallet.prototype.sendTx = function(ntxid, cb) {
var tx = txp.builder.build(); var tx = txp.builder.build();
if (!tx.isComplete()) if (!tx.isComplete())
throw new Error('Tx is not complete. Can not broadcast'); throw new Error('Tx is not complete. Can not broadcast');
log.debug('Broadcasting Transaction'); log.debug('Wallet:' + this.id +' Broadcasting Transaction');
var scriptSig = tx.ins[0].getScript(); var scriptSig = tx.ins[0].getScript();
var size = scriptSig.serialize().length; var size = scriptSig.serialize().length;
var txHex = tx.serialize().toString('hex'); var txHex = tx.serialize().toString('hex');
log.debug('Raw transaction: ', txHex); log.debug('Wallet:' + this.id +' Raw transaction: ', txHex);
var self = this; var self = this;
this.blockchain.broadcast(txHex, function(err, txid) { this.blockchain.broadcast(txHex, function(err, txid) {
log.debug('BITCOIND txid:', txid); log.debug('Wallet:' + self.id +' BITCOIND txid:', txid);
if (txid) { if (txid) {
self.txProposals.get(ntxid).setSent(txid); self.txProposals.get(ntxid).setSent(txid);
self.sendTxProposal(ntxid); self.sendTxProposal(ntxid);
self.store(); self.store();
return cb(txid); return cb(txid);
} else { } else {
log.debug('Sent failed. Checking if the TX was sent already'); log.debug('Wallet:' + self.id +' Sent failed. Checking if the TX was sent already');
self._checkSentTx(ntxid, function(txid) { self._checkSentTx(ntxid, function(txid) {
if (txid) if (txid)
self.store(); self.store();
@ -1651,7 +1686,6 @@ Wallet.prototype.sendPaymentTx = function(ntxid, options, cb) {
options = {}; options = {};
} }
console.log('[Wallet.js.1613:ntxid:]',ntxid); //TODO
var txp = this.txProposals.get(ntxid); var txp = this.txProposals.get(ntxid);
if (!txp) return; if (!txp) return;
@ -2427,7 +2461,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
*/ */
Wallet.prototype.updateIndexes = function(callback) { Wallet.prototype.updateIndexes = function(callback) {
var self = this; var self = this;
log.debug('Updating indexes...'); log.debug('Wallet:' + this.id +' Updating indexes...');
var tasks = this.publicKeyRing.indexes.map(function(index) { var tasks = this.publicKeyRing.indexes.map(function(index) {
return function(callback) { return function(callback) {
@ -2437,7 +2471,7 @@ Wallet.prototype.updateIndexes = function(callback) {
async.parallel(tasks, function(err) { async.parallel(tasks, function(err) {
if (err) callback(err); if (err) callback(err);
log.debug('Indexes updated'); log.debug('Wallet:' + self.id +' Indexes updated');
self.emit('publicKeyRingUpdated'); self.emit('publicKeyRingUpdated');
self.store(); self.store();
callback(); callback();
@ -2544,8 +2578,9 @@ Wallet.prototype.indexDiscovery = function(start, change, copayerIndex, gap, cb)
* @desc Closes the wallet and disconnects all services * @desc Closes the wallet and disconnects all services
*/ */
Wallet.prototype.close = function(cb) { Wallet.prototype.close = function(cb) {
var self = this;
this.network.cleanUp(); this.network.cleanUp();
this.blockchain.destroy();
log.debug('## CLOSING Wallet: ' + this.id); log.debug('## CLOSING Wallet: ' + this.id);
this.lock.release(function() { this.lock.release(function() {
if (cb) return cb(); if (cb) return cb();

View file

@ -186,10 +186,10 @@ angular.module('copayApp.services')
root.bindWallet = function(w, $scope) { root.bindWallet = function(w, $scope) {
root.setupRootVariables(); root.setupRootVariables();
root.unbindWallet(w);
root.installWalletHandlers(w, $scope); root.installWalletHandlers(w, $scope);
root.updateAddressList(); root.updateAddressList();
notification.enableHtml5Mode(); // for chrome: if support, enable it notification.enableHtml5Mode(); // for chrome: if support, enable it
w.netStart();
}; };
// TODO movie this to wallet // TODO movie this to wallet

View file

@ -83,12 +83,12 @@ describe('PayPro (in Wallet) model', function() {
c.networkName = walletConfig.networkName; c.networkName = walletConfig.networkName;
c.version = '0.0.1'; c.version = '0.0.1';
c.network = sinon.stub(); c.network = sinon.stub();
c.network.setHexNonce = sinon.stub(); c.network.setHexNonce = sinon.stub();
c.network.setHexNonces = sinon.stub(); c.network.setHexNonces = sinon.stub();
c.network.getHexNonce = sinon.stub(); c.network.getHexNonce = sinon.stub();
c.network.getHexNonces = sinon.stub(); c.network.getHexNonces = sinon.stub();
c.network.send = sinon.stub(); c.network.send = sinon.stub();
return new Wallet(c); return new Wallet(c);
@ -130,7 +130,15 @@ describe('PayPro (in Wallet) model', function() {
cachedW2obj = cachedW2.toObj(); cachedW2obj = cachedW2.toObj();
cachedW2obj.opts.reconnectDelay = 100; cachedW2obj.opts.reconnectDelay = 100;
} }
var w = Wallet.fromObj(cachedW2obj, cachedW2.storage, cachedW2.network, cachedW2.blockchain);
Wallet._newAsync = sinon.stub().returns(new Network(walletConfig.network));
Wallet._newInsight = sinon.stub().returns(new Blockchain(walletConfig.blockchain));
var w = Wallet.fromObj(cachedW2obj, {
storage: cachedW2.storage,
blockchainOpts: {},
networkOpts: {},
});
return w; return w;
}; };
@ -745,7 +753,10 @@ describe('PayPro (in Wallet) model', function() {
uri = address.split(/\s+/)[1]; uri = address.split(/\s+/)[1];
} }
w.createPaymentTx({ uri: uri, memo: commentText }, function(err, ntxid, merchantData) { w.createPaymentTx({
uri: uri,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null); should.equal(err, null);
if (w.isShared()) { if (w.isShared()) {
should.exist(ntxid); should.exist(ntxid);
@ -767,7 +778,10 @@ describe('PayPro (in Wallet) model', function() {
should.exist(w); should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request'; var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.'; var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({ uri: address, memo: commentText }, function(err, ntxid, merchantData) { w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null); should.equal(err, null);
if (w.isShared()) { if (w.isShared()) {
should.exist(ntxid); should.exist(ntxid);
@ -788,7 +802,10 @@ describe('PayPro (in Wallet) model', function() {
should.exist(w); should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request'; var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.'; var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({ uri: address, memo: commentText }, function(err, ntxid, merchantData) { w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null); should.equal(err, null);
should.exist(ntxid); should.exist(ntxid);
should.exist(merchantData); should.exist(merchantData);
@ -825,7 +842,10 @@ describe('PayPro (in Wallet) model', function() {
should.exist(w); should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request'; var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.'; var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({ uri: address, memo: commentText }, function(err, ntxid, merchantData) { w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null); should.equal(err, null);
should.exist(ntxid); should.exist(ntxid);
should.exist(merchantData); should.exist(merchantData);
@ -853,7 +873,10 @@ describe('PayPro (in Wallet) model', function() {
should.exist(w); should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request'; var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.'; var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({ uri: address, memo: commentText }, function(err, ntxid, merchantData) { w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null); should.equal(err, null);
should.exist(ntxid); should.exist(ntxid);
should.exist(merchantData); should.exist(merchantData);
@ -880,7 +903,10 @@ describe('PayPro (in Wallet) model', function() {
should.exist(w); should.exist(w);
var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request'; var address = 'bitcoin:2NBzZdFBoQymDgfzH2Pmnthser1E71MmU47?amount=0.00003&r=' + server.uri + '/request';
var commentText = 'Hello, server. I\'d like to make a payment.'; var commentText = 'Hello, server. I\'d like to make a payment.';
w.createPaymentTx({ uri: address, memo: commentText }, function(err, ntxid, merchantData) { w.createPaymentTx({
uri: address,
memo: commentText
}, function(err, ntxid, merchantData) {
should.equal(err, null); should.equal(err, null);
should.exist(ntxid); should.exist(ntxid);
should.exist(merchantData); should.exist(merchantData);

View file

@ -27,8 +27,23 @@ var walletConfig = {
reconnectDelay: 100, reconnectDelay: 100,
networkName: 'testnet', networkName: 'testnet',
storage: requireMock('FakeLocalStorage').storageParams, storage: requireMock('FakeLocalStorage').storageParams,
// network layer config
networkOpts: {
testnet: {
url: 'https://test-insight.bitpay.com:443',
transports: ['polling'],
},
livenet: {
url: 'https://insight.bitpay.com:443',
transports: ['polling'],
},
},
}; };
walletConfig.blockchainOpts = walletConfig.networkOpts;
var getNewEpk = function() { var getNewEpk = function() {
return new PrivateKey({ return new PrivateKey({
networkName: walletConfig.networkName, networkName: walletConfig.networkName,
@ -81,11 +96,19 @@ describe('Wallet model', function() {
var storage = new Storage(walletConfig.storage); var storage = new Storage(walletConfig.storage);
storage._setPassphrase('xxx'); storage._setPassphrase('xxx');
var network = new Network(walletConfig.network);
var blockchain = new Blockchain(walletConfig.blockchain); c.blockchain = new Blockchain(walletConfig.blockchain);
c.storage = storage; c.storage = storage;
c.network = network;
c.blockchain = blockchain; c.network = sinon.stub();
c.network.setHexNonce = sinon.stub();
c.network.setHexNonces = sinon.stub();
c.network.getHexNonce = sinon.stub();
c.network.getHexNonces = sinon.stub();
c.network.peerFromCopayer = sinon.stub().returns('xxxx');
c.network.send = sinon.stub();
c.addressBook = { c.addressBook = {
'2NFR2kzH9NUdp8vsXTB4wWQtTtzhpKxsyoJ': { '2NFR2kzH9NUdp8vsXTB4wWQtTtzhpKxsyoJ': {
@ -105,7 +128,6 @@ describe('Wallet model', function() {
c.networkName = walletConfig.networkName; c.networkName = walletConfig.networkName;
c.version = '0.0.1'; c.version = '0.0.1';
return new Wallet(c); return new Wallet(c);
} }
@ -117,7 +139,14 @@ describe('Wallet model', function() {
cachedWobj = cachedW.toObj(); cachedWobj = cachedW.toObj();
cachedWobj.opts.reconnectDelay = 100; cachedWobj.opts.reconnectDelay = 100;
} }
var w = Wallet.fromObj(cachedWobj, cachedW.storage, cachedW.network, cachedW.blockchain); Wallet._newAsync = sinon.stub().returns(new Network(walletConfig.network));
Wallet._newInsight = sinon.stub().returns(new Blockchain(walletConfig.blockchain));
var w = Wallet.fromObj(cachedWobj, {
storage: cachedW.storage,
blockchainOpts: {},
networkOpts: {},
});
return w; return w;
}; };
@ -183,10 +212,18 @@ describe('Wallet model', function() {
cachedW2obj = cachedW2.toObj(); cachedW2obj = cachedW2.toObj();
cachedW2obj.opts.reconnectDelay = 100; cachedW2obj.opts.reconnectDelay = 100;
} }
var w = Wallet.fromObj(cachedW2obj, cachedW2.storage, cachedW2.network, cachedW2.blockchain); Wallet._newAsync = sinon.stub().returns(new Network(walletConfig.network));
Wallet._newInsight = sinon.stub().returns(new Blockchain(walletConfig.blockchain));
var w = Wallet.fromObj(cachedW2obj, {
storage: cachedW2.storage,
blockchainOpts: {},
networkOpts: {},
});
return w; return w;
}; };
it('#create, fail for network', function() { it('#create, fail for network', function() {
var w = cachedCreateW2(); var w = cachedCreateW2();
@ -343,10 +380,11 @@ describe('Wallet model', function() {
var s = new Storage(walletConfig.storage); var s = new Storage(walletConfig.storage);
s._setPassphrase('xxx'); s._setPassphrase('xxx');
var w2 = Wallet.fromObj(o, var w2 = Wallet.fromObj(o, {
s, storage: s,
new Network(walletConfig.network), blockchainOpts: {},
new Blockchain(walletConfig.blockchain)); networkOpts: {},
});
should.exist(w2); should.exist(w2);
w2.publicKeyRing.requiredCopayers.should.equal(w.publicKeyRing.requiredCopayers); w2.publicKeyRing.requiredCopayers.should.equal(w.publicKeyRing.requiredCopayers);
should.exist(w2.publicKeyRing.getCopayerId); should.exist(w2.publicKeyRing.getCopayerId);
@ -613,8 +651,10 @@ describe('Wallet model', function() {
var newId = '00bacacafe'; var newId = '00bacacafe';
it('handle new connections', function(done) { it('handle new connections', function(done) {
var w = createW(); var w = createW();
w.sendWalletId = sinon.stub();
w.on('connect', function(id) { w.on('connect', function(id) {
id.should.equal(newId); id.should.equal('xxxx');
done(); done();
}); });
w._onConnect(newId); w._onConnect(newId);
@ -1849,7 +1889,12 @@ describe('Wallet model', function() {
var blockchain = new Blockchain(walletConfig.blockchain); var blockchain = new Blockchain(walletConfig.blockchain);
it('Import backup using old copayerIndex', function() { it('Import backup using old copayerIndex', function() {
var w = Wallet.fromObj(JSON.parse(o), storage, network, blockchain);
var w = Wallet.fromObj(JSON.parse(o), {
storage: storage,
blockchainOpts: {},
networkOpts: {},
});
should.exist(w); should.exist(w);
w.id.should.equal("dbfe10c3fae71cea"); w.id.should.equal("dbfe10c3fae71cea");
@ -1860,7 +1905,12 @@ describe('Wallet model', function() {
}); });
it('#fromObj, skipping fields', function() { it('#fromObj, skipping fields', function() {
var w = Wallet.fromObj(JSON.parse(o), storage, network, blockchain, ['publicKeyRing']); var w = Wallet.fromObj(JSON.parse(o), {
storage: storage,
networkOpts: {},
blockchainOpts: {},
skipFields: ['publicKeyRing'],
});
should.exist(w); should.exist(w);
w.id.should.equal("dbfe10c3fae71cea"); w.id.should.equal("dbfe10c3fae71cea");
@ -1876,7 +1926,11 @@ describe('Wallet model', function() {
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet"},"addressBook":{}}'; var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet"},"addressBook":{}}';
var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":0},{"copayerIndex":0,"changeIndex":0,"receiveIndex":0},{"copayerIndex":1,"changeIndex":0,"receiveIndex":0},{"copayerIndex":2,"changeIndex":0,"receiveIndex":0},{"copayerIndex":3,"changeIndex":0,"receiveIndex":0},{"copayerIndex":4,"changeIndex":0,"receiveIndex":0}],"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet"},"addressBook":{}}'; var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":0},{"copayerIndex":0,"changeIndex":0,"receiveIndex":0},{"copayerIndex":1,"changeIndex":0,"receiveIndex":0},{"copayerIndex":2,"changeIndex":0,"receiveIndex":0},{"copayerIndex":3,"changeIndex":0,"receiveIndex":0},{"copayerIndex":4,"changeIndex":0,"receiveIndex":0}],"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet"},"addressBook":{}}';
var w = Wallet.fromObj(JSON.parse(o), storage, network, blockchain); var w = Wallet.fromObj(JSON.parse(o), {
storage: storage,
networkOpts: {},
blockchainOpts: {},
});
should.exist(w); should.exist(w);
w.id.should.equal("dbfe10c3fae71cea"); w.id.should.equal("dbfe10c3fae71cea");
@ -1889,18 +1943,25 @@ describe('Wallet model', function() {
}); });
describe('#read', function() { describe('#read', function() {
var storage, network, blockchain;
var s = function() {}; beforeEach(function() {
var storage = new s(); var s = function() {};
var network = new Network(walletConfig.network); storage = new s();
var blockchain = new Blockchain(walletConfig.blockchain); network = new Network(walletConfig.network);
storage.setPassword = sinon.stub(); blockchain = new Blockchain(walletConfig.blockchain);
storage.setPassword = sinon.stub();
});
it('should fail to read an unexisting wallet', function(done) { it('should fail to read an unexisting wallet', function(done) {
storage.getFirst = sinon.stub().yields(null); storage.getFirst = sinon.stub().yields(null);
Wallet.read('123', storage, network, blockchain, [], function(err, w) { Wallet.read('123', {
storage: storage,
networkOpts: {},
blockchainOpts: {},
}, function(err, w) {
err.toString().should.contain('WNOTFOUND'); err.toString().should.contain('WNOTFOUND');
done(); done();
}); });
@ -1910,7 +1971,11 @@ describe('Wallet model', function() {
storage.getFirst = sinon.stub().yields(null, '{hola:1}'); storage.getFirst = sinon.stub().yields(null, '{hola:1}');
Wallet.read('123', storage, network, blockchain, [], function(err, w) { Wallet.read('123', {
storage: storage,
networkOpts: {},
blockchainOpts: {},
}, function(err, w) {
err.toString().should.contain('WERROR'); err.toString().should.contain('WERROR');
done(); done();
}); });
@ -1918,7 +1983,11 @@ describe('Wallet model', function() {
it('should read a wallet', function(done) { it('should read a wallet', function(done) {
storage.getFirst = sinon.stub().yields(null, JSON.parse(o)); storage.getFirst = sinon.stub().yields(null, JSON.parse(o));
Wallet.read('123', storage, network, blockchain, [], function(err, w) { Wallet.read('123', {
storage: storage,
networkOpts: {},
blockchainOpts: {},
}, function(err, w) {
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
@ -1926,7 +1995,11 @@ describe('Wallet model', function() {
it('should be able to import unencrypted legacy wallet TxProposal: v0', function(done) { it('should be able to import unencrypted legacy wallet TxProposal: v0', function(done) {
storage.getFirst = sinon.stub().yields(null, JSON.parse(legacyO)); storage.getFirst = sinon.stub().yields(null, JSON.parse(legacyO));
Wallet.read('123', storage, network, blockchain, [], function(err, w) { Wallet.read('123', {
storage: storage,
networkOpts: {},
blockchainOpts: {},
}, function(err, w) {
should.exist(w); should.exist(w);
w.id.should.equal('55d4bd062d32f90a'); w.id.should.equal('55d4bd062d32f90a');
should.exist(w.publicKeyRing.getCopayerId); should.exist(w.publicKeyRing.getCopayerId);
@ -1939,7 +2012,11 @@ describe('Wallet model', function() {
it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function(done) { it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function(done) {
storage.getFirst = sinon.stub().yields(null, JSON.parse(legacy1)); storage.getFirst = sinon.stub().yields(null, JSON.parse(legacy1));
Wallet.read('123', storage, network, blockchain, [], function(err, w) { Wallet.read('123', {
storage: storage,
networkOpts: {},
blockchainOpts: {},
}, function(err, w) {
should.exist(w); should.exist(w);
w.isReady().should.equal(true); w.isReady().should.equal(true);
var wo = w.toObj(); var wo = w.toObj();

View file

@ -6,7 +6,6 @@ var chai = chai || require('chai');
var should = chai.should(); var should = chai.should();
var FakeNetwork = requireMock('FakeNetwork');
var FakeBlockchain = requireMock('FakeBlockchain'); var FakeBlockchain = requireMock('FakeBlockchain');
var FakeStorage = function FakeStorage() {}; var FakeStorage = function FakeStorage() {};
var Identity = copay.Identity; var Identity = copay.Identity;
@ -338,7 +337,8 @@ describe('Identity model', function() {
}; };
it('should yield bad network error', function(done) { it('should yield bad network error', function(done) {
var net = iden.networks['testnet']; var net = sinon.stub();
net.greet = sinon.stub(); net.greet = sinon.stub();
net.cleanUp = sinon.stub(); net.cleanUp = sinon.stub();
net.start = sinon.stub().yields(null); net.start = sinon.stub().yields(null);
@ -348,6 +348,8 @@ describe('Identity model', function() {
networkName: 'aWeirdNetworkName', networkName: 'aWeirdNetworkName',
opts: {}, opts: {},
}); });
Identity._newAsync = function() { return net; };
opts.privHex = undefined; opts.privHex = undefined;
iden.joinWallet(opts, function(err, w) { iden.joinWallet(opts, function(err, w) {
err.should.equal('badNetwork'); err.should.equal('badNetwork');
@ -358,7 +360,7 @@ describe('Identity model', function() {
it('should yield to join error', function(done) { it('should yield to join error', function(done) {
opts.privHex = undefined; opts.privHex = undefined;
var net = iden.networks['testnet']; var net = sinon.stub();
net.greet = sinon.stub(); net.greet = sinon.stub();
net.cleanUp = sinon.stub(); net.cleanUp = sinon.stub();
net.start = sinon.stub().yields(null); net.start = sinon.stub().yields(null);
@ -369,6 +371,8 @@ describe('Identity model', function() {
type: 'walletId', type: 'walletId',
networkName: iden.networkName, networkName: iden.networkName,
}); });
Identity._newAsync = function() { return net; };
iden.joinWallet(opts, function(err, w) { iden.joinWallet(opts, function(err, w) {
err.should.equal('joinError'); err.should.equal('joinError');
done(); done();
@ -378,7 +382,7 @@ describe('Identity model', function() {
it('should call network.start / create', function(done) { it('should call network.start / create', function(done) {
opts.privHex = undefined; opts.privHex = undefined;
var net = iden.networks['testnet']; var net = sinon.stub();
net.cleanUp = sinon.spy(); net.cleanUp = sinon.spy();
net.greet = sinon.spy(); net.greet = sinon.spy();
net.start = sinon.stub().yields(null); net.start = sinon.stub().yields(null);
@ -390,6 +394,7 @@ describe('Identity model', function() {
networkName: 'testnet', networkName: 'testnet',
opts: {}, opts: {},
}); });
Identity._newAsync = function() { return net; };
var w = sinon.stub(); var w = sinon.stub();
w.sendWalletReady = sinon.spy(); w.sendWalletReady = sinon.spy();
@ -407,7 +412,7 @@ describe('Identity model', function() {
it('should return walletFull', function(done) { it('should return walletFull', function(done) {
opts.privHex = undefined; opts.privHex = undefined;
var net = iden.networks['testnet']; var net = sinon.stub();
net.cleanUp = sinon.spy(); net.cleanUp = sinon.spy();
net.greet = sinon.spy(); net.greet = sinon.spy();
net.start = sinon.stub().yields(null); net.start = sinon.stub().yields(null);
@ -419,6 +424,7 @@ describe('Identity model', function() {
networkName: 'testnet', networkName: 'testnet',
opts: {}, opts: {},
}); });
Identity._newAsync = function() { return net; };
iden.createWallet = sinon.stub().yields(null, null); iden.createWallet = sinon.stub().yields(null, null);
iden.joinWallet(opts, function(err, w) { iden.joinWallet(opts, function(err, w) {
err.should.equal('walletFull'); err.should.equal('walletFull');
@ -428,7 +434,10 @@ describe('Identity model', function() {
it('should accept a priv key a input', function() { it('should accept a priv key a input', function() {
opts.privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd'; opts.privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd';
var net = iden.networks['testnet']; var net = sinon.stub();
Identity._newAsync = function() { return net; };
net.on = sinon.stub();
net.cleanUp = sinon.spy(); net.cleanUp = sinon.spy();
net.start = sinon.spy(); net.start = sinon.spy();
iden.joinWallet(opts, function(err, w) { iden.joinWallet(opts, function(err, w) {
@ -437,9 +446,11 @@ describe('Identity model', function() {
}); });
it('should call network.start with private key', function() { it('should call network.start with private key', function() {
opts.privHex = undefined; opts.privHex = undefined;
var net = iden.networks['testnet']; var net = sinon.stub();
net.cleanUp = sinon.spy(); net.cleanUp = sinon.spy();
net.on = sinon.stub();
net.start = sinon.spy(); net.start = sinon.spy();
Identity._newAsync = function() { return net; };
iden.joinWallet(opts, function(err, w) { iden.joinWallet(opts, function(err, w) {
net.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer net.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer
}); });