Merge pull request #181 from matiu/walletNames

add wallets nicknames, handle error messages
This commit is contained in:
Mario Colque 2014-04-24 16:44:19 -03:00
commit 9acff3db3f
8 changed files with 98 additions and 48 deletions

View file

@ -17,7 +17,13 @@
<a href="#"><img src="./img/logo-negative.svg" alt="Copay" width="130" /></a> <a href="#"><img src="./img/logo-negative.svg" alt="Copay" width="130" /></a>
</figure> </figure>
<div class="text-right" ng-show="$root.wallet"> <div class="text-right" ng-show="$root.wallet">
<h5 ng-show="$root.wallet.id">Wallet ID: {{$root.wallet.id}}</h5> <div ng-if="$root.wallet.name">
<h5>Wallet: {{$root.wallet.name}} &lt;{{$root.wallet.id}}&gt;</h5>
<p>
</div>
<div ng-if="!$root.wallet.name && $root.wallet.id">
<h5 >Wallet ID: {{$root.wallet.id}}</h5>
</div>
<p> <p>
Balance: {{totalBalance || 0}} <i class="fi-bitcoin"></i><br> Balance: {{totalBalance || 0}} <i class="fi-bitcoin"></i><br>
Available to Spend: {{availableBalance || 0}} <i class="fi-bitcoin"></i> Available to Spend: {{availableBalance || 0}} <i class="fi-bitcoin"></i>
@ -98,7 +104,7 @@
Connecting to wallet... Connecting to wallet...
</div> </div>
<div ng-show="!loading"> <div ng-show="!loading">
<div ng-show="!walletIds.length"> <div ng-show="!wallets.length">
<div class="row"> <div class="row">
<div class="large-6 columns"> <div class="large-6 columns">
<h3>Create a New Wallet</h3> <h3>Create a New Wallet</h3>
@ -109,12 +115,12 @@
</div> </div>
<hr> <hr>
</div> </div>
<div ng-show="walletIds.length"> <div ng-show="wallets.length">
<div class="row"> <div class="row">
<div class="large-6 columns"> <div class="large-6 columns">
<h3>Open Wallet</h3> <h3>Open Wallet</h3>
<select class="form-control" ng-model="selectedWalletId" <select class="form-control" ng-model="selectedWalletId"
ng-options="walletId for walletId in walletIds"> ng-options="w.id as w.show for w in wallets">
</select> </select>
</div> </div>
<div class="large-3 columns"> <div class="large-3 columns">
@ -141,7 +147,7 @@
<div class="row"> <div class="row">
<div class="large-12 columns"> <div class="large-12 columns">
<div ng-show="walletIds.length"> <div ng-show="wallets.length">
<a ng-click="create()">Create a new wallet</a> <a ng-click="create()">Create a new wallet</a>
</div> </div>
<a class="right" ng-click="import()">Import from file</a> <a class="right" ng-click="import()">Import from file</a>
@ -176,10 +182,15 @@
ng-options="requiredCopayers as requiredCopayers for requiredCopayers in RCValues"> ng-options="requiredCopayers as requiredCopayers for requiredCopayers in RCValues">
</select> </select>
</div> </div>
<div class="large-6 large-centered columns"> <div class="large-6 large-centered columns m30v">
<h6>Wallet name (optional)</h6>
<input ng-model="walletName" placeholder="wallet name" class="size-24" style="width:100%">
</div>
<div class="large-6 large-centered columns m30v">
<hr> <hr>
<button class="button primary round right" type="button" <button class="button primary round right" type="button"
ng-click="create(totalCopayers, requiredCopayers)"> ng-click="create(totalCopayers, requiredCopayers, walletName)">
Create {{requiredCopayers}}-of-{{totalCopayers}} wallet Create {{requiredCopayers}}-of-{{totalCopayers}} wallet
</button> </button>
<div class="left"> <div class="left">

View file

@ -26,11 +26,12 @@ angular.module('copay.setup').controller('SetupController',
updateRCSelect(tc); updateRCSelect(tc);
}); });
$scope.create = function(totalCopayers, requiredCopayers) { $scope.create = function(totalCopayers, requiredCopayers, walletName) {
$scope.loading = true; $scope.loading = true;
var opts = { var opts = {
requiredCopayers: requiredCopayers, requiredCopayers: requiredCopayers,
totalCopayers: totalCopayers totalCopayers: totalCopayers,
name: walletName,
}; };
var w = walletFactory.create(opts); var w = walletFactory.create(opts);
controllerUtils.setupUxHandlers(w); controllerUtils.setupUxHandlers(w);

View file

@ -3,8 +3,8 @@
angular.module('copay.signin').controller('SigninController', angular.module('copay.signin').controller('SigninController',
function($scope, $rootScope, $location, walletFactory, controllerUtils) { function($scope, $rootScope, $location, walletFactory, controllerUtils) {
$scope.loading = false; $scope.loading = false;
$scope.walletIds = walletFactory.getWalletIds(); $scope.wallets = walletFactory.getWallets();
$scope.selectedWalletId = $scope.walletIds.length ? $scope.walletIds[0]:null; $scope.selectedWalletId = $scope.wallets.length ? $scope.wallets[0].id : null;
$scope.create = function() { $scope.create = function() {
$location.path('setup'); $location.path('setup');
@ -12,14 +12,13 @@ angular.module('copay.signin').controller('SigninController',
$scope.open = function(walletId, opts) { $scope.open = function(walletId, opts) {
$scope.loading = true; $scope.loading = true;
console.log('[signin.js.23:walletId:]',walletId); //TODO
var w = walletFactory.open(walletId, opts); var w = walletFactory.open(walletId, opts);
controllerUtils.setupUxHandlers(w); controllerUtils.setupUxHandlers(w);
}; };
$scope.join = function(secret) { $scope.join = function(secret) {
if (!secret || !secret.length) { if (!secret || secret.length !==66 || !secret.match(/^[0-9a-f]*$/) ) {
$rootScope.flashMessage = { message: 'Bad secret secret string', type: 'error'};
return; return;
} }
$scope.loading = true; $scope.loading = true;

View file

@ -25,6 +25,7 @@ function Wallet(opts) {
this.log('creating '+opts.requiredCopayers+' of '+opts.totalCopayers+' wallet'); this.log('creating '+opts.requiredCopayers+' of '+opts.totalCopayers+' wallet');
this.id = opts.id || Wallet.getRandomId(); this.id = opts.id || Wallet.getRandomId();
this.name = opts.name;
this.verbose = opts.verbose; this.verbose = opts.verbose;
this.publicKeyRing.walletId = this.id; this.publicKeyRing.walletId = this.id;
this.txProposals.walletId = this.id; this.txProposals.walletId = this.id;
@ -137,6 +138,7 @@ Wallet.prototype._optsToObj = function () {
spendUnconfirmed: this.spendUnconfirmed, spendUnconfirmed: this.spendUnconfirmed,
requiredCopayers: this.requiredCopayers, requiredCopayers: this.requiredCopayers,
totalCopayers: this.totalCopayers, totalCopayers: this.totalCopayers,
name: this.name,
}; };
return obj; return obj;
@ -172,6 +174,7 @@ Wallet.prototype.netStart = function() {
copayerId: myId, copayerId: myId,
signingKeyHex: self.privateKey.getSigningKey(), signingKeyHex: self.privateKey.getSigningKey(),
}; };
net.start(startOpts, function() { net.start(startOpts, function() {
self.emit('created'); self.emit('created');
for (var i=0; i<self.publicKeyRing.registeredCopayers(); i++) { for (var i=0; i<self.publicKeyRing.registeredCopayers(); i++) {
@ -518,6 +521,8 @@ Wallet.prototype.connectTo = function(peerId) {
}; };
Wallet.prototype.disconnect = function() { Wallet.prototype.disconnect = function() {
console.log('[Wallet.js.524] DISC'); //TODO
this.network.disconnect(); this.network.disconnect();
}; };

View file

@ -73,7 +73,7 @@ WalletFactory.prototype.read = function(walletId) {
w.privateKey.getExtendedPublicKeyString() w.privateKey.getExtendedPublicKeyString()
); );
} catch (e) { } catch (e) {
this.log('NOT NECCESARY AN ERROR:', e); //TODO // No really an error, just to be sure.
} }
this.log('### WALLET OPENED:', w.id); this.log('### WALLET OPENED:', w.id);
return w; return w;
@ -129,9 +129,13 @@ WalletFactory.prototype.open = function(walletId, opts) {
return w; return w;
}; };
WalletFactory.prototype.getWalletIds = function() { WalletFactory.prototype.getWallets = function() {
return this.storage.getWalletIds(); var ret = this.storage.getWallets();
} ret.forEach(function(i) {
i.show = i.name ? ( (i.name + ' <'+i.id+'>') ) : i.id;
});
return ret;
};
WalletFactory.prototype.remove = function(walletId) { WalletFactory.prototype.remove = function(walletId) {
// TODO remove wallet contents // TODO remove wallet contents

View file

@ -192,6 +192,7 @@ Network.prototype._onData = function(data, isInbound, peerId) {
Network.prototype._checkAnyPeer = function() { Network.prototype._checkAnyPeer = function() {
if (!this.connectedPeers.length) { if (!this.connectedPeers.length) {
console.log('EMIT openError: no more peers, not even you!'); console.log('EMIT openError: no more peers, not even you!');
this._cleanUp();
this.emit('openError'); this.emit('openError');
} }
} }
@ -251,8 +252,9 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
}); });
p.on('error', function(err) { p.on('error', function(err) {
console.log('### PEER ERROR:', err); if (!err.message.match(/Could\snot\sconnect\sto peer/)) {
//self.disconnect(null, true); // force disconnect console.log('### PEER ERROR:', err);
}
self._checkAnyPeer(); self._checkAnyPeer();
}); });
@ -311,11 +313,12 @@ Network.prototype.start = function(opts, openCallback) {
if (this.started) return openCallback(); if (this.started) return openCallback();
opts.connectedPeers = opts.connectedPeers || []; opts.connectedPeers = opts.connectedPeers || [];
if (!this.copayerId) if (!this.copayerId)
this.setCopayerId(opts.copayerId); this.setCopayerId(opts.copayerId);
if (!this.signingKey) if (!this.signingKey)
this.setSigningKey(opts.signingKeyHex); this.setSigningKey(opts.signingKeyHex);
console.log('CREATING PEER INSTANCE:', this.peerId); //TODO
this.peer = new Peer(this.peerId, this.opts); this.peer = new Peer(this.peerId, this.opts);
this._setupPeerHandlers(openCallback); this._setupPeerHandlers(openCallback);
for (var i = 0; i<opts.connectedPeers.length; i++) { for (var i = 0; i<opts.connectedPeers.length; i++) {
@ -399,27 +402,28 @@ Network.prototype.connectTo = function(copayerId) {
self._setupConnectionHandlers(dataConn, false); self._setupConnectionHandlers(dataConn, false);
}; };
Network.prototype._cleanUp = function() {
self.connectedPeers = [];
self.started = false;
self.peerId = null;
self.copayerId = null;
self.signingKey = null;
if (self.peer) {
console.log('## DESTROYING PEER INSTANCE'); //TODO
self.peer.disconnect();
self.peer.destroy();
self.peer = null;
}
self.closing = 0;
};
Network.prototype.disconnect = function(cb, forced) { Network.prototype.disconnect = function(cb, forced) {
var self = this; var self = this;
self.closing = 1; self.closing = 1;
var cleanUp = function() { this.send(null, { type: 'disconnect' });
self.connectedPeers = []; this._cleanUp();
self.started = false; if (typeof cb === 'function') cb();
self.peerId = null;
if (self.peer) {
self.peer.disconnect();
self.peer.destroy();
self.peer = null;
}
self.closing = 0;
if (typeof cb === 'function') cb();
};
if (!forced) {
this.send(null, { type: 'disconnect' }, cleanUp);
} else {
cleanUp();
}
}; };
module.exports = require('soop')(Network); module.exports = require('soop')(Network);

View file

@ -25,9 +25,9 @@ Storage.prototype._getWalletKeys = function(walletId) {
for (var i = 0; i < localStorage.length; i++) { for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i); var key = localStorage.key(i);
var split = key.split('::'); var split = key.split('::');
if (split.length == 2) { if (split.length == 3) {
if (walletId = split[0]) if (walletId = split[0])
keys.push(split[1]); keys.push(split[2]);
} }
} }
@ -69,30 +69,54 @@ Storage.prototype.remove = function(walletId, k) {
this.removeGlobal(this._key(walletId,k)); this.removeGlobal(this._key(walletId,k));
}; };
Storage.prototype.setName = function(walletId, name) {
this.setGlobal('nameFor::'+walletId, name);
};
Storage.prototype.getName = function(walletId) {
return this.getGlobal('nameFor::'+walletId);
};
Storage.prototype.getWalletIds = function() { Storage.prototype.getWalletIds = function() {
var walletIds = []; var walletIds = [];
var uniq = {}; var uniq = {};
for (var i = 0; i < localStorage.length; i++) { for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i); var key = localStorage.key(i);
var split = key.split('::'); var split = key.split('::');
if (split.length == 2) { if (split.length == 2) {
var walletId = split[0]; var walletId = split[0];
if (walletId === 'nameFor') continue;
if (typeof uniq[walletId] === 'undefined' ) { if (typeof uniq[walletId] === 'undefined' ) {
walletIds.push(walletId); walletIds.push(walletId);
uniq[walletId] = 1; uniq[walletId] = 1;
} }
} }
} }
return walletIds; return walletIds;
}; };
Storage.prototype.getWallets = function() {
var wallets = [];
var uniq = {};
var ids = this.getWalletIds();
for (var i in ids){
wallets.push({
id:ids[i],
name: this.getName(ids[i]),
});
}
return wallets;
};
//obj contains keys to be set //obj contains keys to be set
Storage.prototype.setFromObj = function(walletId, obj) { Storage.prototype.setFromObj = function(walletId, obj) {
for (var k in obj) { for (var k in obj) {
this.set(walletId, k, obj[k]); this.set(walletId, k, obj[k]);
} }
this.setName(walletId, obj.opts.name);
}; };
// remove all values // remove all values

View file

@ -43,6 +43,8 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
root.updateBalance = function() { root.updateBalance = function() {
var w = $rootScope.wallet; var w = $rootScope.wallet;
if (!w) return;
w.getBalance(false,function(balance, balanceByAddr) { w.getBalance(false,function(balance, balanceByAddr) {
$rootScope.totalBalance = balance; $rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr; $rootScope.balanceByAddr = balanceByAddr;