fix conflicts

This commit is contained in:
Mario Colque 2014-04-20 22:54:28 -03:00
commit 009d7b75b8
13 changed files with 261 additions and 113 deletions

View file

@ -86,12 +86,13 @@ body {
color: #111; color: #111;
}*/ }*/
.home .panel { .addresses .panel {
font-size: 0.9rem; font-size: 0.9rem;
} }
.transactions .panel { .transactions .panel {
background: #ECECEC; background: #ECECEC;
border: 1px solid #eee;
} }
.transactions .panel.pending { .transactions .panel.pending {
@ -99,7 +100,25 @@ body {
padding: 1rem; padding: 1rem;
} }
.home .panel:hover { .pending .txheader {
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.pending .txbottom {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #eee;
font-size: 12px;
}
.pending table {
width: 100%;
border: none;
}
.addresses .panel:hover {
background: #efefef; background: #efefef;
} }
@ -185,6 +204,15 @@ small.has-error {
color: #f04124; color: #f04124;
} }
@media (max-width: 641px) {
.hide_menu {
display: none;
}
.show_menu {
display: block;
}
}
hr { margin: 2.25rem 0;} hr { margin: 2.25rem 0;}
button.primary { background-color: #111; } button.primary { background-color: #111; }

View file

@ -27,11 +27,11 @@
<ul class="title-area"> <ul class="title-area">
<li class="name"></li> <li class="name"></li>
<li class="toggle-topbar menu-icon"> <li class="toggle-topbar menu-icon">
<a href="#"> Menu</a> <a ng-click="isCollapsed=!isCollapsed"> Menu</a>
</li> </li>
</ul> </ul>
<section class="top-bar-section"> <section class="top-bar-section {{isCollapsed && 'hide_menu' || 'show_menu'}}">
<ul> <ul>
<li data-ng-repeat="item in menu" ui-route="/{{item.link}}" class="large-2 text-center" data-ng-class="{active: isActive(item)}"> <li data-ng-repeat="item in menu" ui-route="/{{item.link}}" class="large-2 text-center" data-ng-class="{active: isActive(item)}">
<a href="{{item.link}}"> <i class="{{item.icon}}"></i> {{item.title}}</a> <a href="{{item.link}}"> <i class="{{item.icon}}"></i> {{item.title}}</a>
@ -55,9 +55,9 @@
</div> </div>
<div class="row"> <div class="row">
<div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading' data-alert class="alert-box warning round" > <div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading' data-alert class="alert-box info round" >
<i class="fi-alert size-18"></i> <i class="fi-alert size-18"></i>
NOTE: Your wallet is not complete yet. Note: Your wallet is not complete yet.
<span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()>1"> <span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()>1">
{{$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers() }} keys are {{$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers() }} keys are
</span> </span>
@ -189,8 +189,8 @@
<div class="large-6 columns p70l"> <div class="large-6 columns p70l">
<h3 class="panel-title">Online Copayers: {{$root.wallet.network.connectedPeers.length}}</h3> <h3 class="panel-title">Online Copayers: {{$root.wallet.network.connectedPeers.length}}</h3>
<p class="text-warning" ng-show="$root.wallet.publicKeyRing.requiredCopayers > $root.wallet.network.connectedPeers.length"> <i class="fi-alert size-28"></i> <p class="text-info" ng-show="$root.wallet.publicKeyRing.requiredCopayers > $root.wallet.network.connectedPeers.length"> <i class="fi-alert size-28"></i>
{{$root.wallet.publicKeyRing.requiredCopayers}} copayers needed for signning transactions {{$root.wallet.publicKeyRing.requiredCopayers}} copayers needed for signing transactions
<ul class="no-bullet"> <ul class="no-bullet">
@ -208,9 +208,9 @@
<!-- HOME --> <!-- ADDRESS -->
<script type="text/ng-template" id="home.html"> <script type="text/ng-template" id="addresses.html">
<div class="home" data-ng-controller="HomeController"> <div class="addresses" data-ng-controller="AddressesController">
<div ng-show='$root.wallet.publicKeyRing.isComplete()'> <div ng-show='$root.wallet.publicKeyRing.isComplete()'>
<h3>Address</h3> <h3>Address</h3>
<div class="row"> <div class="row">
@ -221,8 +221,7 @@
<qrcode size="160" data="{{selectedAddr}}"></qrcode> <qrcode size="160" data="{{selectedAddr}}"></qrcode>
<p class="m10t" ng-repeat="addr in addrs" ng-if="selectedAddr==addr"> <strong> {{balanceByAddr[addr]}} BTC </strong> </p> <p class="m10t" ng-repeat="addr in addrs" ng-if="selectedAddr==addr"> <strong> {{balanceByAddr[addr]}} BTC </strong> </p>
</div> </div>
<div class="large-1 columns"> </div> <div class="large-3 columns text-center">
<div class="large-2 columns">
<p> Create a New <strong> Address </strong> </p> <p> Create a New <strong> Address </strong> </p>
<button class="secondary round expand" ng-click="newAddr()"> Create </button> <button class="secondary round expand" ng-click="newAddr()"> Create </button>
</div> </div>
@ -237,36 +236,79 @@
<div class="transactions" data-ng-controller="TransactionsController"> <div class="transactions" data-ng-controller="TransactionsController">
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'> <div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
<div class="large-12 columns"> <div class="large-12 columns">
<h3>Pending Transactions <small>({{txs.length}})</small></h3> <h4>Pending transactions <small>({{txs.length}})</small></h4>
<div class="panel pending" ng-repeat="tx in txs"> <div class="panel pending" ng-repeat="tx in txs">
NTXID: {{tx.ntxid}} <div class="txheader">
CREATOR: {{tx.creator}} <div class="row">
CREATED_TS: {{tx.createdTs}} <div class="large-8 columns">
<div class="row" ng-repeat="o in tx.outs"> ntxid: {{tx.ntxid}}
<p class="large-5 columns"> {{o.value}} BTC </p> </div>
<i class="large-2 columns fi-arrow-right size-16 text-center"></i> <div class="large-4 columns text-right">
<p class="large-5 columns"> {{o.address}}</p> created at {{tx.createdTs | date:'medium'}}
</div>
</div>
</div> </div>
<div class="large-12 columns m0 panel panel-sign" ng-show="tx.signedByUs">
<i class="fi-check size-40"></i> Signed by you already
</div>
<div class="large-12 columns m0" ng-show="!tx.signedByUs">
<div class="line"></div>
<button class="primary round large-4 columns"><i class="large-2 columns fi-x size-16 text-center"></i> Ignore</button>
<small class="large-4 columns text-center">
<span ng-show="tx.missingSignatures==1"> One signature </span>
<span ng-show="tx.missingSignatures>1"> {{tx.missingSignatures}} signatures </span>
missing
</small>
<button class="secondary round large-4 columns" ng-click="sign(tx.ntxid)"><i class="large-2 columns fi-check size-16 text-center"></i> Sign</button>
</div>
</div> <!-- end of row -->
</div> <!-- end of pending -->
<div class="line-dashed-h"></div>
</div>
<div class="row">
<div class="large-12 columns">
<table>
<thead>
<tr>
<th>Creator</th>
<th class="text-center"><i class="fi-arrow-right"></i></th>
<th>To address</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="o in tx.outs">
<td>{{tx.creator}}</td>
<td class="text-center">{{o.value}} BTC</td>
<td>{{o.address}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="txbottom">
<div class="row">
<div class="large-6 columns">
<div ng-show="tx.signedByUs">
<i class="fi-check size-40"></i> Signed by you already
</div>
<div ng-show="!tx.signedByUs">
<button class="secondary round" ng-click="sign(tx.ntxid)">
<i class="fi-check"></i> Sign
</button>
<button class="primary round">
<i class="fi-x"></i> Ignore
</button>
</div>
</div>
<div class="large-6 columns text-right">
<span ng-show="!tx.missingSignatures && !tx.sentTs">
Transaction ready.
<button class="secondary round" ng-click="send(tx.ntxid)">
Broadcast Transaction
</button>
</span>
<span ng-show="!tx.missingSignatures && tx.sentTs">
Sent at {{tx.sentTs | date:'medium'}}
</span>
<span ng-show="tx.missingSignatures==1">
One signature missing
</span>
<span ng-show="tx.missingSignatures>1">
{{tx.missingSignatures}} signatures missing</span>
</div>
</div>
</div>
</div>
</div>
<div class="large-12 columns"> <div class="large-12 columns">
<h3>Last Transactions</h3> <!--
<h4>Last transactions</h4>
<div class="panel"> <div class="panel">
<div class="row"> <div class="row">
<p class="large-5 columns"> Address 1 <small class="right"> 1231 BTC </small></p> <p class="large-5 columns"> Address 1 <small class="right"> 1231 BTC </small></p>
@ -297,6 +339,7 @@ missing
</span> </span>
</div> </div>
</div> </div>
-->
</div> </div>
</div> </div>
</div> </div>
@ -307,7 +350,7 @@ missing
<div class="send" data-ng-controller="SendController"> <div class="send" data-ng-controller="SendController">
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'> <div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
<div class="small-6 large-centered columns"> <div class="small-6 large-centered columns">
<h1>{{title}}</h1> <h3>{{title}}</h3>
<form name="sendForm" ng-submit="submitForm(sendForm)" novalidate> <form name="sendForm" ng-submit="submitForm(sendForm)" novalidate>
<div class="row"> <div class="row">
<div class="large-12 columns"> <div class="large-12 columns">
@ -347,10 +390,6 @@ missing
</div> </div>
</div> </div>
</form> </form>
<hr>
<div class="text-center">
<a ng-click="sendTest()">sendTest</a>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -359,7 +398,7 @@ missing
<!-- BACKUP --> <!-- BACKUP -->
<script type="text/ng-template" id="backup.html"> <script type="text/ng-template" id="backup.html">
<div class="backup" data-ng-controller="BackupController"> <div class="backup" data-ng-controller="BackupController">
<h2>{{title}}</h2> <h3>{{title}}</h3>
<div class="row text-center"> <div class="row text-center">
<div class="large-4 columns"> <div class="large-4 columns">
<a class="panel box-backup" ng-click="download()"> <a class="panel box-backup" ng-click="download()">
@ -416,7 +455,7 @@ missing
<script src="js/services/controllerUtils.js"></script> <script src="js/services/controllerUtils.js"></script>
<script src="js/controllers/header.js"></script> <script src="js/controllers/header.js"></script>
<script src="js/controllers/home.js"></script> <script src="js/controllers/addresses.js"></script>
<script src="js/controllers/transactions.js"></script> <script src="js/controllers/transactions.js"></script>
<script src="js/controllers/send.js"></script> <script src="js/controllers/send.js"></script>
<script src="js/controllers/backup.js"></script> <script src="js/controllers/backup.js"></script>

View file

@ -5,7 +5,7 @@ angular.module('copay',[
'mm.foundation', 'mm.foundation',
'monospaced.qrcode', 'monospaced.qrcode',
'copay.header', 'copay.header',
'copay.home', 'copay.addresses',
'copay.transactions', 'copay.transactions',
'copay.send', 'copay.send',
'copay.backup', 'copay.backup',
@ -18,7 +18,7 @@ angular.module('copay',[
]); ]);
angular.module('copay.header', []); angular.module('copay.header', []);
angular.module('copay.home', []); angular.module('copay.addresses', []);
angular.module('copay.transactions', []); angular.module('copay.transactions', []);
angular.module('copay.send', []); angular.module('copay.send', []);
angular.module('copay.backup', []); angular.module('copay.backup', []);

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copay.home').controller('HomeController', angular.module('copay.addresses').controller('AddressesController',
function($scope, $rootScope, controllerUtils) { function($scope, $rootScope, controllerUtils) {
$scope.title = 'Home'; $scope.title = 'Home';
$scope.oneAtATime = true; $scope.oneAtATime = true;

View file

@ -3,13 +3,13 @@
angular.module('copay.header').controller('HeaderController', angular.module('copay.header').controller('HeaderController',
function($scope, $rootScope, $location, walletFactory, controllerUtils) { function($scope, $rootScope, $location, walletFactory, controllerUtils) {
$scope.menu = [{ $scope.menu = [{
'title': 'Home',
'icon': 'fi-home',
'link': '#/home'
}, {
'title': 'Copayers', 'title': 'Copayers',
'icon': 'fi-torsos-all', 'icon': 'fi-torsos-all',
'link': '#/peer' 'link': '#/peer'
}, {
'title': 'Addresses',
'icon': 'fi-address-book',
'link': '#/addresses'
}, { }, {
'title': 'Transactions', 'title': 'Transactions',
'icon': 'fi-loop', 'icon': 'fi-loop',
@ -49,4 +49,5 @@ angular.module('copay.header').controller('HeaderController',
$rootScope.flashMessage = {}; $rootScope.flashMessage = {};
}; };
$rootScope.isCollapsed = true;
}); });

View file

@ -28,13 +28,6 @@ angular.module('copay.send').controller('SendController',
form.amount.$pristine = true; form.amount.$pristine = true;
// TODO: check if createTx has an error. // TODO: check if createTx has an error.
$rootScope.flashMessage = { message: 'You send a proposal transaction succefully', type: 'success'}; $rootScope.flashMessage = { message: 'Your transaction proposal has been sent successfully', type: 'success'};
}; };
$scope.sendTest = function() {
var w = $rootScope.wallet;
w.createTx( 'mimoZNLcP2rrMRgdeX5PSnR7AjCqQveZZ4', '12345',function() {
$rootScope.$digest();
});
};
}); });

View file

@ -8,6 +8,7 @@ angular.module('copay.transactions').controller('TransactionsController',
$scope.oneAtATime = true; $scope.oneAtATime = true;
var _updateTxs = function() { var _updateTxs = function() {
console.log('[transactions.js.10:_updateTxs:]'); //TODO
var w =$rootScope.wallet; var w =$rootScope.wallet;
var inT = w.getTxProposals(); var inT = w.getTxProposals();
var txs = []; var txs = [];
@ -35,11 +36,28 @@ angular.module('copay.transactions').controller('TransactionsController',
one.missingSignatures = tx.countInputMissingSignatures(0); one.missingSignatures = tx.countInputMissingSignatures(0);
one.signedByUs = i.signedByUs; one.signedByUs = i.signedByUs;
one.ntxid = i.ntxid; one.ntxid = i.ntxid;
one.creator = i.txp.creator, one.creator = i.txp.creator;
one.createdTs = i.txp.createdTs; one.createdTs = i.txp.createdTs;
one.sentTs = i.txp.sentTs;
txs.push(one); txs.push(one);
}); });
$scope.txs = txs; $scope.txs = txs;
console.log('[transactions.js.55] SET HANDL+'); //TODO
w.removeListener('txProposalsUpdated',_updateTxs)
w.once('txProposalsUpdated',_updateTxs);
};
$scope.send = function (ntxid) {
var w = $rootScope.wallet;
w.sendTx(ntxid, function(txid) {
console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO
$rootScope.flashMessage = txid
? {type:'success', message: 'Transactions SENT! txid:' + txid}
: {type:'error', message: 'There was an error sending the Transaction'}
;
_updateTxs();
$rootScope.$digest();
});
}; };
$scope.sign = function (ntxid) { $scope.sign = function (ntxid) {
@ -49,19 +67,16 @@ angular.module('copay.transactions').controller('TransactionsController',
var p = w.getTxProposal(ntxid); var p = w.getTxProposal(ntxid);
if (p.txp.builder.isFullySigned()) { if (p.txp.builder.isFullySigned()) {
w.sendTx(ntxid, function(txid) { $scope.send(ntxid);
$rootScope.flashMessage = txid
? {type:'success', message: 'Transactions SENT! txid:' + txid}
: {type:'error', message: 'There was an error sending the Transaction'}
;
});
} }
else { else {
$rootScope.flashMessage = ret $rootScope.flashMessage = ret
? {type:'success', message: 'Transactions signed'} ? {type:'success', message: 'Transactions signed'}
: {type:'error', message: 'There was an error signing the Transaction'} : {type:'error', message: 'There was an error signing the Transaction'}
; ;
_updateTxs();
$rootScope.$digest();
} }
_updateTxs();
}; };
}); });

View file

@ -70,7 +70,10 @@ Insight.prototype.sendRawTransaction = function(rawtx, cb) {
headers: { 'content-type' : 'application/x-www-form-urlencoded' } headers: { 'content-type' : 'application/x-www-form-urlencoded' }
}; };
this._request(options, function(err,res) { this._request(options, function(err,res) {
console.log('[Insight.js.73:err:]',err); //TODO
if (err) return cb(); if (err) return cb();
console.log('[Insight.js.74]', res); //TODO
return cb(res.txid); return cb(res.txid);
}); });
}; };
@ -95,13 +98,18 @@ Insight.prototype._request = function(options, callback) {
request.open(options.method, url, true); request.open(options.method, url, true);
request.onreadystatechange = function() { request.onreadystatechange = function() {
if (request.readyState === 4) { if (request.readyState === 4) {
console.log('[Insight.js.102]', request); //TODO
if (request.status === 200) { if (request.status === 200) {
try { try {
return callback(null, JSON.parse(request.responseText)); return callback(null, JSON.parse(request.responseText));
} catch (e) { } catch (e) {
console.log('[Insight.js.106]'); //TODO
return callback({message: 'Wrong response from insight'}); return callback({message: 'Wrong response from insight'});
} }
} else { } else {
console.log('[Insight.js.111]'); //TODO
return callback({message: 'Error ' + request.status}); return callback({message: 'Error ' + request.status});
} }
} }

View file

@ -19,6 +19,7 @@ function TxProposal(opts) {
this.seenBy = opts.seenBy || {}; this.seenBy = opts.seenBy || {};
this.signedBy = opts.signedBy || {}; this.signedBy = opts.signedBy || {};
this.builder = opts.builder; this.builder = opts.builder;
this.sentTs = opts.sentTs || null;
} }
TxProposal.prototype.toObj = function() { TxProposal.prototype.toObj = function() {
@ -28,6 +29,11 @@ TxProposal.prototype.toObj = function() {
return o; return o;
}; };
TxProposal.prototype.setSent = function() {
this.sentTs = Date.now();;
};
TxProposal.fromObj = function(o) { TxProposal.fromObj = function(o) {
var t = new TxProposal(o); var t = new TxProposal(o);
var b = new Builder.fromObj(o.builderObj); var b = new Builder.fromObj(o.builderObj);
@ -35,6 +41,10 @@ TxProposal.fromObj = function(o) {
return t; return t;
}; };
TxProposal.getSentTs = function() {
return this.sentTs;
};
module.exports = require('soop')(TxProposal); module.exports = require('soop')(TxProposal);
@ -54,6 +64,7 @@ TxProposals.fromObj = function(o) {
o.txps.forEach(function(o2) { o.txps.forEach(function(o2) {
var t = TxProposal.fromObj(o2); var t = TxProposal.fromObj(o2);
var id = t.builder.build().getNormalizedHash().toString('hex'); var id = t.builder.build().getNormalizedHash().toString('hex');
console.log('[TxProposals.js.65:id:]',id, o2); //TODO
ret.txps[id] = t; ret.txps[id] = t;
}); });
return ret; return ret;
@ -64,7 +75,8 @@ TxProposals.prototype.toObj = function() {
var ret = []; var ret = [];
for(var id in this.txps){ for(var id in this.txps){
var t = this.txps[id]; var t = this.txps[id];
ret.push(t.toObj()); if (!t.sent)
ret.push(t.toObj());
} }
return { return {
txps: ret, txps: ret,
@ -110,43 +122,66 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
var toMerge = mergeInfo.toMerge; var toMerge = mergeInfo.toMerge;
var hasChanged =0;
Object.keys(toMerge).forEach(function(hash) { Object.keys(toMerge).forEach(function(hash) {
var v0 = myTxps[hash]; var v0 = myTxps[hash];
var v1 = toMerge[hash]; var v1 = toMerge[hash];
console.log('[TxProposals.js.127:v0:]',v0, v1); //TODO
Object.keys(v1.seenBy).forEach(function(k) { Object.keys(v1.seenBy).forEach(function(k) {
v0.seenBy[k] = v1.seenBy[k]; if (!v0.seenBy[k] || v0.seenBy[k] !== v1.seenBy[k]) {
v0.seenBy[k] = v1.seenBy[k];
hasChanged++;
}
}); });
Object.keys(v1.signedBy).forEach(function(k) { Object.keys(v1.signedBy).forEach(function(k) {
v0.signedBy[k] = v1.signedBy[k]; if (!v0.signedBy[k]) {
v0.signedBy[k] = v1.signedBy[k];
hasChanged++;
}
}); });
if (!v0.sentTs && v1.sentTs) {
v0.sentTs = v1.sentTs;
hasChanged++;
}
}); });
console.log('[TxProposals.js.131:hasChanged:]',hasChanged); //TODO
return hasChanged;
}; };
TxProposals.prototype._mergeBuilder = function(myTxps, theirTxps, mergeInfo) { TxProposals.prototype._mergeBuilder = function(myTxps, theirTxps, mergeInfo) {
var toMerge = mergeInfo.toMerge; var toMerge = mergeInfo.toMerge;
var hasChanged=0;
for(var hash in toMerge){ for(var hash in toMerge){
var v0 = myTxps[hash].builder; var v0 = myTxps[hash].builder;
var v1 = toMerge[hash].builder; var v1 = toMerge[hash].builder;
// TODO: enhance this
var before = JSON.stringify(v0.toObj());
v0.merge(v1); v0.merge(v1);
}; var after = JSON.stringify(v0.toObj());
if (after !== before) hasChanged ++;
}
console.log('[TxProposals.js.149:hasChanged:]',hasChanged); //TODO
}; };
TxProposals.prototype.add = function(data) { TxProposals.prototype.add = function(data) {
var id = data.builder.build().getNormalizedHash().toString('hex'); var id = data.builder.build().getNormalizedHash().toString('hex');
console.log('[TxProposals.js.175:data: ADD]',data); //TODO
this.txps[id] = new TxProposal(data); this.txps[id] = new TxProposal(data);
}; };
TxProposals.prototype.remove = function(ntxid) { TxProposals.prototype.setSent = function(ntxid) {
//sent TxProposals are local an not broadcasted.
console.log('[TxProposals.js.147] DELETING:', ntxid); //TODO console.log('[TxProposals.js.147] SET SENT:', ntxid); //TODO
delete this.txps[ntxid]; this.txps[ntxid].setSent();
}; };
@ -155,18 +190,21 @@ TxProposals.prototype.merge = function(t) {
throw new Error('network mismatch in:', t); throw new Error('network mismatch in:', t);
var res = []; var res = [];
var hasChanged = 0;
var myTxps = this.txps; var myTxps = this.txps;
var theirTxps = t.txps; var theirTxps = t.txps;
var mergeInfo = this._startMerge(myTxps, theirTxps); var mergeInfo = this._startMerge(myTxps, theirTxps);
this._mergeMetadata(myTxps, theirTxps, mergeInfo); hasChanged += this._mergeMetadata(myTxps, theirTxps, mergeInfo);
this._mergeBuilder(myTxps, theirTxps, mergeInfo); hasChanged += this._mergeBuilder(myTxps, theirTxps, mergeInfo);
Object.keys(mergeInfo.toMerge).forEach(function(hash) { Object.keys(mergeInfo.toMerge).forEach(function(hash) {
mergeInfo.ready[hash] = myTxps[hash]; mergeInfo.ready[hash] = myTxps[hash];
}); });
mergeInfo.stats.hasChanged = hasChanged;
this.txps=mergeInfo.ready; this.txps=mergeInfo.ready;
return mergeInfo.stats; return mergeInfo.stats;
}; };

View file

@ -34,7 +34,8 @@ function Wallet(opts) {
Wallet.parent=EventEmitter; Wallet.parent=EventEmitter;
Wallet.prototype.log = function(){ Wallet.prototype.log = function(){
if (!this.verbose) return; if (!this.verbose) return;
console.log(arguments); if (console)
console.log.apply(console, arguments);
}; };
Wallet.getRandomId = function() { Wallet.getRandomId = function() {
@ -76,10 +77,13 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
var recipients; var recipients;
var inTxp = copay.TxProposals.fromObj(data.txProposals); var inTxp = copay.TxProposals.fromObj(data.txProposals);
var mergeInfo = this.txProposals.merge(inTxp, true); var mergeInfo = this.txProposals.merge(inTxp, true);
console.log('[Wallet.js.79:inTxp:]',inTxp); //TODO
var addSeen = this.addSeenToTxProposals(); var addSeen = this.addSeenToTxProposals();
console.log('[Wallet.js.81]', addSeen, mergeInfo); //TODO
// if ((mergeInfo.merged && !data.isBroadcast) || addSeen) { // if ((mergeInfo.merged && !data.isBroadcast) || addSeen) {
if (mergeInfo.merged || addSeen) { if (mergeInfo.hasChanged || addSeen) {
this.log('### BROADCASTING txProposals. ' ); this.log('### BROADCASTING txProposals. ' );
recipients = null; recipients = null;
shouldSend = true; shouldSend = true;
@ -191,6 +195,8 @@ console.log('[Wallet.js.177] NET START: emit CREATED'); //TODO
if (otherPeerId !== myPeerId) { if (otherPeerId !== myPeerId) {
net.connectTo(otherPeerId); net.connectTo(otherPeerId);
} }
self.sendWalletReady(self.firstPeerId);
self.firstPeerId = null;
self.emit('refresh'); self.emit('refresh');
} }
}, startOpts); }, startOpts);
@ -203,7 +209,8 @@ Wallet.prototype.store = function(isSync) {
if (isSync) { if (isSync) {
this.log('Wallet stored.'); //TODO this.log('Wallet stored.'); //TODO
} else { }
else {
this.log('Wallet stored. REFRESH Emitted'); //TODO this.log('Wallet stored. REFRESH Emitted'); //TODO
this.emit('refresh'); this.emit('refresh');
} }
@ -291,7 +298,7 @@ Wallet.prototype.getTxProposals = function() {
var txp = this.txProposals.txps[k]; var txp = this.txProposals.txps[k];
var i = {txp:txp}; var i = {txp:txp};
i.ntxid = k; i.ntxid = k;
i.signedByUs = txp.signedBy[this.privateKey.getId()]?true:false; i.signedByUs = txp.signedBy[this.getMyPeerId()]?true:false;
ret.push(i); ret.push(i);
} }
return ret; return ret;
@ -301,7 +308,7 @@ Wallet.prototype.getTxProposal = function(ntxid) {
var txp = this.txProposals.txps[ntxid]; var txp = this.txProposals.txps[ntxid];
var i = {txp:txp}; var i = {txp:txp};
i.ntxid = ntxid; i.ntxid = ntxid;
i.signedByUs = txp.signedBy[this.privateKey.getId()]?true:false; i.signedByUs = txp.signedBy[this.getMyPeerId()]?true:false;
return i; return i;
}; };
@ -319,7 +326,7 @@ Wallet.prototype.sign = function(ntxid) {
var ret = false; var ret = false;
if (b.signaturesAdded > before) { if (b.signaturesAdded > before) {
txp.signedBy[self.privateKey.getId()] = Date.now(); txp.signedBy[self.getMyPeerId()] = Date.now();
this.sendTxProposals(); this.sendTxProposals();
this.store(true); this.store(true);
ret = true; ret = true;
@ -327,7 +334,7 @@ Wallet.prototype.sign = function(ntxid) {
return ret; return ret;
}; };
Wallet.prototype.sendTx = function(ntxid) { Wallet.prototype.sendTx = function(ntxid, cb) {
var txp = this.txProposals.txps[ntxid]; var txp = this.txProposals.txps[ntxid];
if (!txp) return; if (!txp) return;
@ -342,21 +349,25 @@ Wallet.prototype.sendTx = function(ntxid) {
this.blockchain.sendRawTransaction(txHex, function(txid) { this.blockchain.sendRawTransaction(txHex, function(txid) {
self.log('BITCOND txid:',txid); //TODO self.log('BITCOND txid:',txid); //TODO
if (txid) { if (txid) {
self.txProposals.remove(ntxid); self.txProposals.setSent(ntxid);
self.store(true);
} }
return (txid); self.sendTxProposals();
self.store();
return cb(txid);
}); });
}; };
Wallet.prototype.addSeenToTxProposals = function() { Wallet.prototype.addSeenToTxProposals = function() {
var ret=false; var ret=false;
var self=this; var myId=this.getMyPeerId();
for(var k in this.txProposals.txps) { for(var k in this.txProposals.txps) {
var txp = this.txProposals.txps[k]; var txp = this.txProposals.txps[k];
if (!txp.seenBy[self.privateKey.getId()]) { console.log('[Wallet.js.364:txp:] ADD SEEN',txp); //TODO
txp.seenBy[self.privateKey.getId()] = Date.now(); if (!txp.seenBy[myId]) {
console.log('[Wallet.js.367] ADDING'); //TODO
txp.seenBy[myId] = Date.now();
ret = true; ret = true;
} }
} }
@ -435,9 +446,12 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
} }
self.getUnspent(function(unspentList) { self.getUnspent(function(unspentList) {
// TODO check enough funds, etc. // TODO check enough funds, etc.
console.log('[Wallet.js.452]', self); //TODO
self.createTxSync(toAddress, amountSatStr, unspentList, opts); self.createTxSync(toAddress, amountSatStr, unspentList, opts);
self.sendPublicKeyRing(); // Change Address self.sendPublicKeyRing(); // Change Address
self.sendTxProposals(); self.sendTxProposals();
console.log('[Wallet.js.452]', self); //TODO
self.store(); self.store();
return cb(); return cb();
}); });
@ -469,15 +483,24 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) ); b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
} }
var me = {}; var me = {};
if (priv) me[priv.getId()] = Date.now(); var myId = this.getMyPeerId();
var now = Date.now();
this.txProposals.add({ if (priv) me[myId] = now;
signedBy: priv && b.signaturesAdded ? me : {},
seenBy: priv ? me : {}, console.log('[Wallet.js.485:me:]',myId, me); //TODO
creator: priv.getId(),
createdTs: Date.now(), var data = {
signedBy: (priv && b.signaturesAdded ? me : {}),
seenBy: (priv ? me : {}),
creator: myId,
createdTs: now,
builder: b, builder: b,
}); };
console.log('[Wallet.js.499:data:]',data); //TODO
this.txProposals.add(data);
}; };
Wallet.prototype.connectTo = function(peerId) { Wallet.prototype.connectTo = function(peerId) {

View file

@ -33,7 +33,8 @@ function WalletFactory(config) {
WalletFactory.prototype.log = function(){ WalletFactory.prototype.log = function(){
if (!this.verbose) return; if (!this.verbose) return;
console.log(arguments); if (console)
console.log.apply(console, arguments);
}; };
@ -152,7 +153,7 @@ WalletFactory.prototype.joinCreateSession = function(peerId, cb) {
if (data.type ==='walletId') { if (data.type ==='walletId') {
data.opts.privateKey = privateKey; data.opts.privateKey = privateKey;
var w = self.open(data.walletId, data.opts); var w = self.open(data.walletId, data.opts);
w.sendWalletReady(peerId); w.firstPeerId = peerId;
return cb(w); return cb(w);
} }
}); });

View file

@ -23,6 +23,7 @@ function Network(opts) {
this.debug = opts.debug || 3; this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 10; this.maxPeers = opts.maxPeers || 10;
this.opts = { key: opts.key }; this.opts = { key: opts.key };
this.connections = {};
// For using your own peerJs server // For using your own peerJs server
['port', 'host', 'path', 'debug'].forEach(function(k) { ['port', 'host', 'path', 'debug'].forEach(function(k) {
@ -69,6 +70,9 @@ Network._arrayRemove = function(el, array) {
}; };
Network.prototype._onClose = function(peerId) { Network.prototype._onClose = function(peerId) {
console.log('[WebRTC.js.72:_onClose:]');
delete this.connections[peerId];
this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers); this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers);
this._notifyNetworkChange(); this._notifyNetworkChange();
}; };
@ -138,11 +142,11 @@ Network.prototype._checkAnyPeer = function() {
} }
Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) { Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
var self=this; var self=this;
dataConn.on('open', function() { dataConn.on('open', function() {
if (!Network._inArray(dataConn.peer, self.connectedPeers)) { if (!Network._inArray(dataConn.peer, self.connectedPeers)) {
self.connections[dataConn.peer] = dataConn;
console.log('### DATA CONNECTION READY TO: ADDING PEER: %s (inbound: %s)', console.log('### DATA CONNECTION READY TO: ADDING PEER: %s (inbound: %s)',
dataConn.peer, isInbound); dataConn.peer, isInbound);
@ -159,11 +163,14 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
dataConn.on('error', function(e) { dataConn.on('error', function(e) {
console.log('### DATA ERROR',e ); //TODO console.log('### DATA ERROR',e ); //TODO
self._onClose(dataConn.peer);
self._checkAnyPeer();
self.emit('dataError'); self.emit('dataError');
}); });
dataConn.on('close', function() { dataConn.on('close', function() {
if (self.closing) return; if (self.closing) return;
console.log('### CLOSE RECV FROM:', dataConn.peer); console.log('### CLOSE RECV FROM:', dataConn.peer);
self._onClose(dataConn.peer); self._onClose(dataConn.peer);
self._checkAnyPeer(); self._checkAnyPeer();
@ -181,8 +188,6 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
p.on('open', function() { p.on('open', function() {
self.connectedPeers = [self.peerId]; self.connectedPeers = [self.peerId];
console.log('[WebRTC.js.187] LENGTH', self.connectedPeers.length); //TODO
return openCallback(); return openCallback();
}); });
@ -239,18 +244,16 @@ console.log('[WebRTC.js.237] started TRUE'); //TODO
Network.prototype._sendToOne = function(peerId, data, cb) { Network.prototype._sendToOne = function(peerId, data, cb) {
if (peerId !== this.peerId) { if (peerId !== this.peerId) {
var conns = this.peer.connections[peerId]; var dataConn = this.connections[peerId];
if (dataConn) {
if (conns) {
var str = JSON.stringify({ var str = JSON.stringify({
sender: this.peerId, sender: this.peerId,
data: data data: data
}); });
dataConn.send(str);
for (var i = 0; i < conns.length; i++) { }
var conn = conns[i]; else {
conn.send(str); console.log('[WebRTC.js.255] WARN: NO CONNECTION TO:', peerId); //TODO
}
} }
} }
if (typeof cb === 'function') cb(); if (typeof cb === 'function') cb();

View file

@ -18,9 +18,8 @@ angular
templateUrl: 'setup.html', templateUrl: 'setup.html',
validate: false validate: false
}) })
.when('/home', { .when('/addresses', {
templateUrl: 'home.html', templateUrl: 'addresses.html'
validate: true
}) })
.when('/join/:id', { .when('/join/:id', {
templateUrl: 'join.html', templateUrl: 'join.html',