fix conflicts

This commit is contained in:
Matias Alejo Garcia 2014-06-24 13:02:25 -03:00
commit f1257d054c
49 changed files with 1015 additions and 755 deletions

View file

@ -15,7 +15,7 @@ html, body {height: 100%;}
#main { #main {
overflow:auto; overflow:auto;
padding-bottom: 91px;} /* must be same height as the footer */ padding-bottom: 80px;} /* must be same height as the footer */
.main-home { .main-home {
padding-bottom: 28px !important; padding-bottom: 28px !important;
@ -37,9 +37,8 @@ html, body {height: 100%;}
#footer { #footer {
position: fixed; position: fixed;
margin-top: -96px; /* negative value of footer height */ margin-top: -80px; /* negative value of footer height */
height: 70px;
height: 80px;
clear:both; clear:both;
padding: 5px 2rem; padding: 5px 2rem;
bottom: 0; bottom: 0;
@ -65,7 +64,6 @@ html, body {height: 100%;}
.logo { .logo {
display: block; display: block;
height: 51px; height: 51px;
margin: 0 auto;
} }
.top-bar-section li:not(.has-form) a:not(.button) { .top-bar-section li:not(.has-form) a:not(.button) {
@ -173,12 +171,6 @@ h3 {
border-right: 2px dashed #E3E3E3; border-right: 2px dashed #E3E3E3;
} }
@media (max-width: 640px) {
.line-dashed-v {
border: none;
}
}
.line-dashed-h { .line-dashed-h {
margin: 1rem 0; margin: 1rem 0;
border-bottom: 2px dashed #E3E3E3; border-bottom: 2px dashed #E3E3E3;
@ -238,28 +230,13 @@ input[type=number]::-webkit-outer-spin-button {
line-height: inherit; line-height: inherit;
} }
@media (max-width: 641px) {
.hide_menu {
display: none;
}
.show_menu {
display: block;
}
.top-bar-section ul li {
width: 100%;
}
}
@media (max-width: 750px) {
.top-bar-section ul li>a {
font-size: 70%;
}
}
.new-address { .new-address {
width: 220px; width: 220px;
} }
.transactions button, .transactions .button {
padding: 0.5rem 2rem;
}
hr { margin: 2.25rem 0;} hr { margin: 2.25rem 0;}
@ -406,10 +383,13 @@ hr { margin: 2.25rem 0;}
margin-right: 10px; margin-right: 10px;
margin-bottom: 10px; margin-bottom: 10px;
border: 3px solid #eee; border: 3px solid #eee;
opacity: 0.3;
border-radius: 0.3rem;
} }
.box-setup-copay-required { .box-setup-copay-required {
border: 3px solid green; border: 3px solid #1ABC9C;
opacity: 1;
} }
.tx-copayers { .tx-copayers {
@ -655,52 +635,3 @@ ul.pagination li.current a:hover, ul.pagination li.current a:focus {
color:white; color:white;
} }
@media only screen and (max-width: 40em) {
#main, .header-content {
font-size: 80%;
line-height: 140%;
}
.top-bar {
background: #1ABC9C;
}
.header-content {
padding: 0.3rem 0rem 1rem 0.4rem;
}
.logo {
background-size: 90px 44px !important;
float: left;
margin-top: 0.7rem;
width: 130px;
}
.header-content .small-9 {
text-align: right !important;
}
.header-content .line-dashed-v {
border: none !important;
}
.box-backup {
margin: 0.6rem 0;
}
#footer {
font-size: 80%;
padding: 0.2rem 0.5rem;
}
.box-status {
height: 71px;
}
.box-copayers figure {
height: 71px;
width: 71px;
}
}

50
css/mobile.css Normal file
View file

@ -0,0 +1,50 @@
@media (max-width: 1024px) {
.logo {
background-size: 90px 44px !important;
height: 41px;
}
.header-content {
font-size: 70%;
line-height: 120%;
font-weight: normal;
}
.line-dashed-v {
border: none !important;
}
.top-bar-section ul li>a {
font-size: 70%;
}
}
@media (max-width: 640px) {
.hide_menu {
display: none;
}
.show_menu {
display: block;
}
.top-bar-section ul li {
width: 100%;
}
.top-bar-section ul li>a {
padding: 0 0 0 15px;
}
.top-bar {
background: #1ABC9C;
}
.header-content .small-7 {
text-align: right !important;
padding-top: 0;
}
.box-copayers figure {
height: 71px;
width: 71px;
}
}

View file

@ -175,10 +175,6 @@ small.has-error {
border-radius: 10px; border-radius: 10px;
} }
.transactions button, .transactions .button {
padding: 0.5rem 2rem;
}
button.radius, .button.radius { button.radius, .button.radius {
-webkit-border-radius: 5px; -webkit-border-radius: 5px;
border-radius: 5px; border-radius: 5px;
@ -325,3 +321,28 @@ input.ng-invalid-wallet-secret {
background: #fff; background: #fff;
} }
.tooltip {
background: #16A085;
color: #fff;
font-weight: normal;
font-size: 12px;
padding: 3px 5px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #16A085;
}
.tooltip>.nub {
border-color:transparent transparent #16A085 transparent;
}
.tooltip.tip-top>.nub {
border-color:#16A085 transparent transparent transparent;
}
.tooltip.tip-right>.nub {
border-color:transparent #16A085 transparent transparent;
}
.tooltip.tip-left>.nub {
border-color:transparent transparent transparent #16A085;
}

View file

@ -9,6 +9,7 @@
<link rel="stylesheet" href="css/foundation-icons.css"> <link rel="stylesheet" href="css/foundation-icons.css">
<link rel="stylesheet" href="lib/angular/angular-csp.css"> <link rel="stylesheet" href="lib/angular/angular-csp.css">
<link rel="stylesheet" href="css/main.css"> <link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/mobile.css">
<link rel="shortcut icon" href="img/favicon.ico"> <link rel="shortcut icon" href="img/favicon.ico">
</head> </head>
<body ng-cloak class="ng-cloak"> <body ng-cloak class="ng-cloak">
@ -16,10 +17,10 @@
<div data-ng-init="init()" data-ng-controller="HeaderController"> <div data-ng-init="init()" data-ng-controller="HeaderController">
<div class="header"> <div class="header">
<div class="header-content"> <div class="header-content">
<div class="large-3 medium-3 small-3 columns"> <div class="large-3 medium-3 small-5 columns">
<span class="logo"></span> <span class="logo"></span>
</div> </div>
<div class="large-9 medium-9 small-9 columns text-center p10t" ng-show="$root.wallet"> <div class="large-9 medium-9 small-7 columns text-center p10t" ng-show="$root.wallet && $root.wallet.publicKeyRing.isComplete()">
<div class="large-4 medium-4 columns line-dashed-v"> <div class="large-4 medium-4 columns line-dashed-v">
<a href="#/addresses" class="has-tip" tooltip-placement="bottom" tooltip="ID: {{$root.wallet.id}}"> <a href="#/addresses" class="has-tip" tooltip-placement="bottom" tooltip="ID: {{$root.wallet.id}}">
<strong><span>{{$root.wallet.getName()}}</span></strong> <strong><span>{{$root.wallet.getName()}}</span></strong>
@ -31,26 +32,26 @@
ng-click="signout()"><i class="fi-power"></i></a> ng-click="signout()"><i class="fi-power"></i></a>
</div> </div>
<div class="large-4 medium-4 columns line-dashed-v"> <div class="large-4 medium-4 columns line-dashed-v">
Balance<br> Balance<br class="hide-for-small">
<span ng-if="$root.updatingBalance"> <span ng-if="$root.updatingBalance">
<i class="fi-bitcoin-circle icon-rotate spinner"></i> <i class="fi-bitcoin-circle icon-rotate spinner"></i>
</span> </span>
<span ng-if="!$root.updatingBalance" tooltip="{{totalBalanceBTC}} BTC" tooltip-trigger="mouseenter" tooltip-placement="bottom">{{totalBalance || 0 |number}} {{$root.unitName}} <span ng-if="!$root.updatingBalance" data-options="disable_for_touch:true" tooltip="{{totalBalanceBTC}} BTC" tooltip-trigger="mouseenter" tooltip-placement="bottom">{{totalBalance || 0 |number}} {{$root.unitName}}
</span> </span>
</div> </div>
<div class="large-4 medium-4 columns"> <div class="large-4 medium-4 columns">
Available to Spend<br> Available to Spend<br class="hide-for-small">
<span ng-if="$root.updatingBalance"> <span ng-if="$root.updatingBalance">
<i class="fi-bitcoin-circle icon-rotate spinner"></i> <i class="fi-bitcoin-circle icon-rotate spinner"></i>
</span> </span>
<span ng-show="!$root.updatingBalance" tooltip="{{availableBalanceBTC}} BTC" tooltip-trigger="mouseenter" tooltip-placement="bottom">{{availableBalance || 0|number}} {{$root.unitName}} <span ng-show="!$root.updatingBalance" data-options="disable_for_touch:true" tooltip="{{availableBalanceBTC}} BTC" tooltip-trigger="mouseenter" tooltip-placement="bottom">{{availableBalance || 0|number}} {{$root.unitName}}
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<nav class="top-bar" data-topbar ng-show="$root.wallet"> <nav class="top-bar" data-topbar ng-show="$root.wallet && $root.wallet.publicKeyRing.isComplete()">
<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">
@ -99,9 +100,9 @@
</div> </div>
</div> </div>
<div class="row">
<div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading'> <div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading'>
<div class="medium-12 small-12 columns"> <div class="row">
<div class="large-12 medium-12 small-12 columns">
<div class="alert-box secondary radius" data-alert> <div class="alert-box secondary radius" data-alert>
<i class="fi-info"></i> <i class="fi-info"></i>
Not all copayers have joined your wallet yet. Not all copayers have joined your wallet yet.
@ -114,8 +115,10 @@
yet to join. yet to join.
</div> </div>
</div> </div>
</div>
<div class="medium-12 small-12 columns "> <div class="row">
<div class="large-12 medium-12 small-12 columns ">
<div class="panel radius m30v"> <div class="panel radius m30v">
<h3 class="m15b">Share this secret with your other copayers <h3 class="m15b">Share this secret with your other copayers
<small> for them to join your wallet</small> <small> for them to join your wallet</small>
@ -134,18 +137,27 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="large-12 medium-12 small-12 columns ">
<div class="box-setup-copayers">
<div class="box-setup-copayers-fix">
<img class="box-setup-copay" ng-repeat="i in getNumber($root.wallet.totalCopayers) track by $index" src="./img/satoshi.gif" alt="Copayer {{$index+1}}-{{totalCopayers}}" ng-class="{'box-setup-copay-required': ($index+1) <= $root.wallet.publicKeyRing.registeredCopayers()}">
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div notifications="middle right"></div> <div notifications="middle right"></div>
<div id="main" class="row" ng-class="{'main-home': !$root.wallet}"> <div id="main" class="row" ng-class="{'main-home': !$root.wallet || !$root.wallet.publicKeyRing.isComplete()}">
<div class="large-12 columns" ng-view></div> <div class="large-12 columns" ng-view></div>
</div> </div>
</div> </div>
<div id="footer" data-ng-controller="FooterController" ng-class="{'footer-home': !$root.wallet}"> <div id="footer" data-ng-controller="FooterController" ng-class="{'footer-home': !$root.wallet || !$root.wallet.publicKeyRing.isComplete()}">
<link rel="stylesheet" ng-href="{{theme}}"> <link rel="stylesheet" ng-href="{{theme}}">
<div ng-show="!$root.wallet"> <div ng-show="!$root.wallet">
<div class="large-12 columns text-left"> <div class="large-12 columns text-left">
@ -153,8 +165,20 @@
<small>v{{version}}</small> <small>v{{version}}</small>
</div> </div>
</div> </div>
<div class="p10t" ng-show="$root.wallet"> <div ng-show="$root.wallet && !$root.wallet.publicKeyRing.isComplete()">
<div class="large-3 medium-3 hide-for-small columns"> <div class="large-6 medium-6 small-6 columns">
<strong>{{$root.wallet.getName()}}</strong>
{{$root.wallet.requiredCopayers}}-of-{{$root.wallet.totalCopayers}}
<small ng-if="$root.wallet.getNetworkName()=='livenet'">[LIVENET]</small>
<small ng-if="$root.wallet.getNetworkName()=='testnet'">[TESTNET]</small>
</div>
<div class="large-6 medium-6 small-6 columns text-right">
Copay
<small>v{{version}}</small>
</div>
</div>
<div ng-show="$root.wallet && $root.wallet.publicKeyRing.isComplete()">
<div class="large-3 medium-4 hide-for-small columns">
<div> <div>
<strong>{{$root.wallet.getName()}}</strong> <strong>{{$root.wallet.getName()}}</strong>
</div> </div>
@ -171,8 +195,7 @@
<a class="size-12" ng-click="change_theme(th)" ng-repeat="th in themes">{{th}} {{$last ? '' : '&middot; '}}</a> <a class="size-12" ng-click="change_theme(th)" ng-repeat="th in themes">{{th}} {{$last ? '' : '&middot; '}}</a>
</div> </div>
</div> </div>
<div class="large-9 medium-9 small-9 columns"> <div class="large-9 medium-8 small-12 columns">
<a href="#/addresses" > </a>
<!-- <div class="bottom&#45;copay" ng&#45;repeat="c in $root.wallet.getRegisteredPeerIds()" class="has&#45;tip" tooltip&#45;popup&#45;delay="1000" tooltip&#45;placement="top" tooltip="{{c.nick}}"> --> <!-- <div class="bottom&#45;copay" ng&#45;repeat="c in $root.wallet.getRegisteredPeerIds()" class="has&#45;tip" tooltip&#45;popup&#45;delay="1000" tooltip&#45;placement="top" tooltip="{{c.nick}}"> -->
<div class="bottom-copay" ng-repeat="c in $root.wallet.getRegisteredPeerIds()"> <div class="bottom-copay" ng-repeat="c in $root.wallet.getRegisteredPeerIds()">
<video ng-if="$root.videoInfo[c.peerId]" <video ng-if="$root.videoInfo[c.peerId]"
@ -312,7 +335,7 @@
</label> </label>
</div> </div>
<div class="small-12 medium-6 large-6 columns"> <div class="small-12 medium-6 large-6 columns">
<label>Your Wallet Password <small class="has-tip" tooltip="doesn't need to be shared">Required</small> <label>Your Wallet Password <small data-options="disable_for_touch:true" class="has-tip" tooltip="doesn't need to be shared">Required</small>
<input type="password" placeholder="Choose your password" class="form-control" <input type="password" placeholder="Choose your password" class="form-control"
ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip-html-unsafe="Password strength: {{passwordStrength}}<br/><small>Tip: Use lower and uppercase, numbers and symbols</small>" tooltip-trigger="focus" required> ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip-html-unsafe="Password strength: {{passwordStrength}}<br/><small>Tip: Use lower and uppercase, numbers and symbols</small>" tooltip-trigger="focus" required>
</label> </label>
@ -390,7 +413,7 @@
</span> </span>
</a> </a>
<a class="secondary radius" ng-click="showAll=!showAll" ng-show="(addresses|withoutFunds) > 1"> <a class="secondary radius" ng-click="showAll=!showAll" ng-show="addresses.length != (addresses|limitAddress).length">
<span ng-if="!showAll">Show all</span> <span ng-if="!showAll">Show all</span>
<span ng-if="showAll">Show less</span> <span ng-if="showAll">Show less</span>
</a> </a>
@ -652,6 +675,7 @@
<div class="row collapse"> <div class="row collapse">
<label for="amount">Amount <label for="amount">Amount
<small ng-hide="!sendForm.amount.$pristine">required</small> <small ng-hide="!sendForm.amount.$pristine">required</small>
<i class="fi-arrow-up" title="Send all funds" ng-click="topAmount()"></i>
<small class="is-valid" ng-show="!sendForm.amount.$invalid && !sendForm.amount.$pristine">Valid</small> <small class="is-valid" ng-show="!sendForm.amount.$invalid && !sendForm.amount.$pristine">Valid</small>
<small class="has-error" ng-show="sendForm.amount.$invalid && !sendForm.amount.$pristine && !notEnoughAmount"> <small class="has-error" ng-show="sendForm.amount.$invalid && !sendForm.amount.$pristine && !notEnoughAmount">
Not valid Not valid
@ -687,14 +711,14 @@
</div> </div>
<div class="row"> <div class="row">
<div class="large-12 medium-6 columns"> <div class="large-12 columns">
<div class="row collapse"> <div class="row collapse">
<label for="comment">Note <label for="comment">Note
<small ng-hide="!sendForm.comment.$pristine">optional</small> <small ng-hide="!sendForm.comment.$pristine">optional</small>
<small class="is-valid" ng-show="!sendForm.comment.$invalid && !sendForm.comment.$pristine">valid!</small> <small class="is-valid" ng-show="!sendForm.comment.$invalid && !sendForm.comment.$pristine">valid!</small>
<small class="has-error" ng-show="sendForm.comment.$invalid && !sendForm.comment.$pristine">too long!</small> <small class="has-error" ng-show="sendForm.comment.$invalid && !sendForm.comment.$pristine">too long!</small>
</label> </label>
<div class="small-12 columns"> <div class="large-12 columns">
<textarea id="comment" ng-disabled="loading" <textarea id="comment" ng-disabled="loading"
name="comment" placeholder="Leave a private message to your copayers" ng-model="commentText" ng-maxlength="100"></textarea> name="comment" placeholder="Leave a private message to your copayers" ng-model="commentText" ng-maxlength="100"></textarea>
</div> </div>
@ -714,7 +738,7 @@
<div class="medium-8 medium-centered large-8 large-centered columns"> <div class="medium-8 medium-centered large-8 large-centered columns">
<hr> <hr>
<h3>Address Book</h3> <h3>Address Book</h3>
<p class="text-gray" ng-hide="showAddressBook()">Empry. Create some alias for addresses</p> <p class="text-gray" ng-hide="showAddressBook()">Empty. Create an alias for your addresses</p>
<table ng-show="showAddressBook()"> <table ng-show="showAddressBook()">
<thead> <thead>
<tr> <tr>
@ -767,16 +791,16 @@
<script type="text/ng-template" id="backup.html"> <script type="text/ng-template" id="backup.html">
<div class="backup" ng-controller="BackupController"> <div class="backup" ng-controller="BackupController">
<h3>{{title}}</h3> <h3>{{title}}</h3>
<div class="row text-center"> <div class="row">
<div class="large-6 medium-6 columns"> <div class="large-4 medium-6 columns large-centered medium-centered">
<a class="panel radius box-backup" ng-click="download()"> <a class="panel radius box-backup text-center" ng-click="download()">
<i class="fi-download size-72"></i> <i class="fi-download size-72"></i>
<p> Download File </p> <p> Download File </p>
</a> </a>
</div> </div>
<div class="row text-center small" style="margin-top:70px">
<div class="button radius warning" ng-really-message="Are you sure to delete this wallet from this computer?" ng-really-click="deleteWallet()">Delete this wallet from this computer</div>
</div> </div>
<div class="row text-center">
<div class="button radius warning small m30v" ng-really-message="Are you sure to delete this wallet from this computer?" ng-really-click="deleteWallet()">Delete this wallet from this computer</div>
</div> </div>
</div> </div>
</script> </script>

View file

@ -34,4 +34,3 @@ angular.module('copayApp.filters', []);
angular.module('copayApp.services', []); angular.module('copayApp.services', []);
angular.module('copayApp.controllers', []); angular.module('copayApp.controllers', []);
angular.module('copayApp.directives', []); angular.module('copayApp.directives', []);

View file

@ -4,8 +4,7 @@ angular.module('copayApp.controllers').controller('FooterController', function($
if (config.themes && Array.isArray(config.themes) && config.themes[0]) { if (config.themes && Array.isArray(config.themes) && config.themes[0]) {
$scope.themes = config.themes; $scope.themes = config.themes;
} } else {
else {
$scope.themes = ['default']; $scope.themes = ['default'];
} }

View file

@ -2,8 +2,7 @@
angular.module('copayApp.controllers').controller('HeaderController', angular.module('copayApp.controllers').controller('HeaderController',
function($scope, $rootScope, $location, notification, $http, controllerUtils) { function($scope, $rootScope, $location, notification, $http, controllerUtils) {
$scope.menu = [ $scope.menu = [{
{
'title': 'Addresses', 'title': 'Addresses',
'icon': 'fi-address-book', 'icon': 'fi-address-book',
'link': '#/addresses' 'link': '#/addresses'
@ -21,14 +20,26 @@ angular.module('copayApp.controllers').controller('HeaderController',
'link': '#/backup' 'link': '#/backup'
}]; }];
$scope.getNumber = function(num) {
return new Array(num);
}
$http.get('https://api.github.com/repos/bitpay/copay/tags').success(function(data) { $http.get('https://api.github.com/repos/bitpay/copay/tags').success(function(data) {
var toInt = function (s) { return parseInt(s); }; var toInt = function(s) {
return parseInt(s);
};
var latestVersion = data[0].name.replace('v', '').split('.').map(toInt); var latestVersion = data[0].name.replace('v', '').split('.').map(toInt);
var currentVersion = copay.version.split('.').map(toInt); var currentVersion = copay.version.split('.').map(toInt);
if (currentVersion[0] < latestVersion[0]) { if (currentVersion[0] < latestVersion[0]) {
$scope.updateVersion = {class: 'error', version:data[0].name}; $scope.updateVersion = {
class: 'error',
version: data[0].name
};
} else if (currentVersion[0] == latestVersion[0] && currentVersion[1] < latestVersion[1]) { } else if (currentVersion[0] == latestVersion[0] && currentVersion[1] < latestVersion[1]) {
$scope.updateVersion = {class: 'info', version:data[0].name}; $scope.updateVersion = {
class: 'info',
version: data[0].name
};
} }
}); });

View file

@ -9,7 +9,10 @@ angular.module('copayApp.controllers').controller('ImportController',
walletFactory.import(encryptedObj, passphrase, function(err, w) { walletFactory.import(encryptedObj, passphrase, function(err, w) {
if (err) { if (err) {
$scope.loading = false; $scope.loading = false;
$rootScope.$flashMessage = { message: err.errMsg || 'Wrong password', type: 'error'}; $rootScope.$flashMessage = {
message: err.errMsg || 'Wrong password',
type: 'error'
};
$rootScope.$digest(); $rootScope.$digest();
return; return;
} }
@ -43,7 +46,10 @@ angular.module('copayApp.controllers').controller('ImportController',
$scope.import = function(form) { $scope.import = function(form) {
if (form.$invalid) { if (form.$invalid) {
$scope.loading = false; $scope.loading = false;
$rootScope.$flashMessage = { message: 'There is an error in the form. Please, try again', type: 'error'}; $rootScope.$flashMessage = {
message: 'There is an error in the form. Please, try again',
type: 'error'
};
return; return;
} }
@ -53,7 +59,10 @@ angular.module('copayApp.controllers').controller('ImportController',
if (!backupFile && !backupText) { if (!backupFile && !backupText) {
$scope.loading = false; $scope.loading = false;
$rootScope.$flashMessage = { message: 'Please, select your backup file or paste the text', type: 'error'}; $rootScope.$flashMessage = {
message: 'Please, select your backup file or paste the text',
type: 'error'
};
$scope.loading = false; $scope.loading = false;
return; return;
} }
@ -62,8 +71,7 @@ angular.module('copayApp.controllers').controller('ImportController',
if (backupFile) { if (backupFile) {
reader.readAsBinaryString(backupFile); reader.readAsBinaryString(backupFile);
} } else {
else {
_importBackup(backupText); _importBackup(backupText);
} }
}; };

View file

@ -33,7 +33,7 @@ angular.module('copayApp.controllers').controller('SendController',
$scope.submitForm = function(form) { $scope.submitForm = function(form) {
if (form.$invalid) { if (form.$invalid) {
$rootScope.$flashMessage = { $rootScope.$flashMessage = {
message: 'You can not send a proposal transaction. Please, try again', message: 'Unable to send a transaction proposal. Please, try again',
type: 'error' type: 'error'
}; };
return; return;
@ -254,4 +254,8 @@ angular.module('copayApp.controllers').controller('SendController',
}); });
}; };
$scope.topAmount = function() {
var maxSat = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT;
$scope.amount = maxSat / config.unitToSatoshi;
};
}); });

View file

@ -1,11 +1,13 @@
'use strict'; 'use strict';
angular.module('copayApp.filters', []) angular.module('copayApp.filters', [])
.filter('amTimeAgo', ['amMoment', function(amMoment) { .filter('amTimeAgo', ['amMoment',
function(amMoment) {
return function(input) { return function(input) {
return amMoment.preprocessDate(input).fromNow(); return amMoment.preprocessDate(input).fromNow();
}; };
}]) }
])
.filter('paged', function() { .filter('paged', function() {
return function(elements) { return function(elements) {
if (elements) { if (elements) {
@ -17,41 +19,15 @@ angular.module('copayApp.filters', [])
}) })
.filter('limitAddress', function() { .filter('limitAddress', function() {
return function(elements, showAll) { return function(elements, showAll) {
var addrs = []; if (elements.length <= 1 || showAll) {
if (elements.length > 0) {
if (showAll) {
return elements; return elements;
} }
if (elements.length == 1) {
return elements;
}
else {
for (var i=0;i<elements.length;i++) {
if (!elements[i].isChange && (!elements[i].balance || elements[i].balance == 0)) {
addrs.push(elements[i]);
break;
}
}
for (var i=0;i<elements.length;i++) { // Show last 3 non-change addresses plus those with balance
if (elements[i].balance && elements[i].balance > 0) { var addrs = elements.filter(function(e, i) {
addrs.push(elements[i]); return (!e.isChange && i < 3) || (e.balance && e.balance > 0);
} });
}
return addrs; return addrs;
}
}
}; };
}) });
.filter('withoutFunds', function() {
return function(elements) {
var len = 0;
for (var i=0;i<elements.length;i++) {
if (!elements[i].balance || elements[i].balance == 0) {
len++;
}
}
return len;
};
})
;

View file

@ -168,14 +168,28 @@ Insight.prototype.checkActivity = function(addresses, cb) {
if (!addresses) throw new Error('address must be set'); if (!addresses) throw new Error('address must be set');
this.getTransactions(addresses, function onResult(txs) { this.getTransactions(addresses, function onResult(txs) {
var flatArray = function (xss) { return xss.reduce(function(r, xs) { return r.concat(xs); }, []); }; var flatArray = function(xss) {
var getInputs = function (t) { return t.vin.map(function (vin) { return vin.addr }); }; return xss.reduce(function(r, xs) {
var getOutputs = function (t) { return flatArray( return r.concat(xs);
t.vout.map(function (vout) { return vout.scriptPubKey.addresses; }) }, []);
);}; };
var getInputs = function(t) {
return t.vin.map(function(vin) {
return vin.addr
});
};
var getOutputs = function(t) {
return flatArray(
t.vout.map(function(vout) {
return vout.scriptPubKey.addresses;
})
);
};
var activityMap = new Array(addresses.length); var activityMap = new Array(addresses.length);
var activeAddress = flatArray(txs.map(function(t) { return getInputs(t).concat(getOutputs(t)); })); var activeAddress = flatArray(txs.map(function(t) {
return getInputs(t).concat(getOutputs(t));
}));
activeAddress.forEach(function(addr) { activeAddress.forEach(function(addr) {
var index = addresses.indexOf(addr); var index = addresses.indexOf(addr);
if (index != -1) activityMap[index] = true; if (index != -1) activityMap[index] = true;

View file

@ -84,8 +84,12 @@ PrivateKey.prototype.getForPath = function(path) {
var derivedHK = this._getHK(path); var derivedHK = this._getHK(path);
pk = this.privateKeyCache[path] = derivedHK.eckey.private.toString('hex'); pk = this.privateKeyCache[path] = derivedHK.eckey.private.toString('hex');
} }
var wk = new WalletKey({network: this.network}); var wk = new WalletKey({
wk.fromObj({priv: pk}); network: this.network
});
wk.fromObj({
priv: pk
});
return wk; return wk;
}; };

View file

@ -146,8 +146,7 @@ Wallet.prototype._handleAddressBook = function(senderId, data, isInbound) {
if (!this.addressBook[key]) { if (!this.addressBook[key]) {
this.addressBook[key] = rcv[key]; this.addressBook[key] = rcv[key];
hasChange = true; hasChange = true;
} } else {
else {
if (rcv[key].createdTs > this.addressBook[key].createdTs) { if (rcv[key].createdTs > this.addressBook[key].createdTs) {
this.addressBook[key] = rcv[key]; this.addressBook[key] = rcv[key];
hasChange = true; hasChange = true;
@ -804,7 +803,9 @@ Wallet.prototype.indexDiscovery = function(start, change, gap, cb) {
next(); next();
}); });
}, },
function _while() { return hasActivity; }, function _while() {
return hasActivity;
},
function _finnaly(err) { function _finnaly(err) {
if (err) return cb(err); if (err) return cb(err);
cb(null, lastActive); cb(null, lastActive);

View file

@ -272,9 +272,7 @@ Network.prototype._addCopayerMap = function(peerId, copayerId) {
if (!this.copayerForPeer[peerId]) { if (!this.copayerForPeer[peerId]) {
if (Object.keys(this.copayerForPeer).length < this.maxPeers) { if (Object.keys(this.copayerForPeer).length < this.maxPeers) {
this.copayerForPeer[peerId] = copayerId; this.copayerForPeer[peerId] = copayerId;
} } else {}
else {
}
} }
}; };
@ -426,7 +424,9 @@ Network.prototype.lockIncommingConnections = function(allowedCopayerIdsArray) {
Network.prototype.disconnect = function(cb, forced) { Network.prototype.disconnect = function(cb, forced) {
var self = this; var self = this;
self.closing = 1; self.closing = 1;
self.send(null, { type: 'disconnect' }, function(){ self.send(null, {
type: 'disconnect'
}, function() {
self.cleanUp(); self.cleanUp();
if (typeof cb === 'function') cb(); if (typeof cb === 'function') cb();
}); });

View file

@ -2,8 +2,7 @@
var imports = require('soop').imports(); var imports = require('soop').imports();
function Storage() { function Storage() {}
}
Storage.prototype._read = function(k) { Storage.prototype._read = function(k) {
var ret; var ret;

View file

@ -67,8 +67,7 @@ angular
if (!util.supports.data) { if (!util.supports.data) {
$location.path('unsupported'); $location.path('unsupported');
} } else {
else {
if ((!$rootScope.wallet || !$rootScope.wallet.id) && next.validate) { if ((!$rootScope.wallet || !$rootScope.wallet.id) && next.validate) {
$location.path('signin'); $location.path('signin');
} }

View file

@ -1,19 +1,41 @@
'use strict'; 'use strict';
angular.module('copayApp.services'). angular.module('copayApp.services').
factory('notification', ['$timeout',function($timeout){ factory('notification', ['$timeout',
function($timeout) {
var notifications = JSON.parse(localStorage.getItem('notifications')) || [], var notifications = JSON.parse(localStorage.getItem('notifications')) || [],
queue = []; queue = [];
var settings = { var settings = {
info: { duration: 5000, enabled: true }, info: {
funds: { duration: 5000, enabled: true }, duration: 5000,
warning: { duration: 5000, enabled: true }, enabled: true
error: { duration: 1e10, enabled: true }, },
success: { duration: 5000, enabled: true }, funds: {
progress: { duration: 0, enabled: true }, duration: 5000,
custom: { duration: 35000, enabled: true }, enabled: true
},
warning: {
duration: 5000,
enabled: true
},
error: {
duration: 1e10,
enabled: true
},
success: {
duration: 5000,
enabled: true
},
progress: {
duration: 0,
enabled: true
},
custom: {
duration: 35000,
enabled: true
},
details: true, details: true,
localStorage: false, localStorage: false,
html5Mode: false, html5Mode: false,
@ -33,8 +55,7 @@ angular.module('copayApp.services').
noti.onclose = onclose; noti.onclose = onclose;
} }
noti.show(); noti.show();
} } else {
else {
settings.html5Mode = false; settings.html5Mode = false;
} }
} }
@ -77,20 +98,17 @@ angular.module('copayApp.services').
if (window.webkitNotifications) { if (window.webkitNotifications) {
if (window.webkitNotifications.checkPermission() === 0) { if (window.webkitNotifications.checkPermission() === 0) {
return true; return true;
} } else {
else{
window.webkitNotifications.requestPermission(function() { window.webkitNotifications.requestPermission(function() {
if (window.webkitNotifications.checkPermission() === 0) { if (window.webkitNotifications.checkPermission() === 0) {
settings.html5Mode = true; settings.html5Mode = true;
} } else {
else{
settings.html5Mode = false; settings.html5Mode = false;
} }
}); });
return false; return false;
} }
} } else {
else{
return false; return false;
} }
}, },
@ -167,8 +185,7 @@ angular.module('copayApp.services').
}, function() { }, function() {
// inner on close function // inner on close function
}); });
} } else {
else{
queue.push(notification); queue.push(notification);
$timeout(function removeFromQueueTimeout() { $timeout(function removeFromQueueTimeout() {
queue.splice(queue.indexOf(notification), 1); queue.splice(queue.indexOf(notification), 1);
@ -200,7 +217,8 @@ angular.module('copayApp.services').
} }
}; };
}]). }
]).
directive('notifications', function(notification, $compile) { directive('notifications', function(notification, $compile) {
/** /**
* *
@ -244,7 +262,8 @@ angular.module('copayApp.services').
scope: {}, scope: {},
template: html, template: html,
link: link, link: link,
controller: ['$scope', function NotificationsCtrl( $scope ){ controller: ['$scope',
function NotificationsCtrl($scope) {
$scope.queue = notification.getQueue(); $scope.queue = notification.getQueue();
$scope.removeNotification = function(noti) { $scope.removeNotification = function(noti) {
@ -255,8 +274,3 @@ angular.module('copayApp.services').
}; };
}); });

View file

@ -1,4 +1,3 @@
'use strict'; 'use strict';
angular.module('copayApp.services').value('walletFactory', new copay.WalletFactory(config, copay.version)); angular.module('copayApp.services').value('walletFactory', new copay.WalletFactory(config, copay.version));

View file

@ -11,13 +11,14 @@
** there to be no references in the window to these libs, so let's trick ** there to be no references in the window to these libs, so let's trick
** the renderer into thinking that we are _not_ in a CommonJS environment. ** the renderer into thinking that we are _not_ in a CommonJS environment.
*/ */
if (typeof module !== 'undefined') module = { exports: null }; if (typeof module !== 'undefined') module = {
exports: null
};
// are we running in copay shell? // are we running in copay shell?
if (window.process && process.type === 'renderer') { if (window.process && process.type === 'renderer') {
window.cshell = initCopayShellBindings(); window.cshell = initCopayShellBindings();
} } else {
else {
return; return;
} }
@ -40,7 +41,9 @@
// atom shell forces to implement the clipboard on our own - thanks obama. // atom shell forces to implement the clipboard on our own - thanks obama.
Mousetrap.stopCallback = function() { return false }; Mousetrap.stopCallback = function() {
return false
};
Mousetrap.bind('ctrl+c', function(e) { Mousetrap.bind('ctrl+c', function(e) {
clipb.writeText(window.getSelection().toString()); clipb.writeText(window.getSelection().toString());

View file

@ -6,7 +6,10 @@
var sys = require('sys') var sys = require('sys')
var exec = require('child_process').exec; var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }
function puts(error, stdout, stderr) {
sys.puts(stdout)
}
function isNumber(n) { function isNumber(n) {
return !isNaN(parseInt(n)) && isFinite(n); return !isNaN(parseInt(n)) && isFinite(n);

View file

@ -1,3 +1,5 @@
if (typeof window != 'undefined') { if (typeof window != 'undefined') {
window.mocha.setup({ timeout: 5000 }); window.mocha.setup({
timeout: 5000
});
} }

View file

@ -1,9 +1,7 @@
var imports = require('soop').imports(); var imports = require('soop').imports();
var EventEmitter = imports.EventEmitter || require('events').EventEmitter; var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
function Network(opts) { function Network(opts) {}
}
Network.parent = EventEmitter; Network.parent = EventEmitter;
@ -34,10 +32,8 @@ Network.prototype.lockIncommingConnections = function() {
}; };
Network.prototype.getPeer = function() { Network.prototype.getPeer = function() {};
}; Network.prototype.connectToCopayers = function(cps) {};
Network.prototype.connectToCopayers = function(cps) {
};
Network.prototype.isOnline = function() { Network.prototype.isOnline = function() {
return true; return true;
}; };

View file

@ -18,7 +18,9 @@ describe('API', function() {
it('should have a command called "echo"', function() { it('should have a command called "echo"', function() {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
should.exist(api.echo); should.exist(api.echo);
}); });
@ -32,7 +34,9 @@ describe('API', function() {
}) })
it('should throw an error for all commands when called with wrong number of arguments', function() { it('should throw an error for all commands when called with wrong number of arguments', function() {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
for (var i in API.prototype) { for (var i in API.prototype) {
var f = API.prototype[i]; var f = API.prototype[i];
if (i[0] != '_' && typeof f == 'function') { if (i[0] != '_' && typeof f == 'function') {
@ -59,7 +63,9 @@ describe('API', function() {
describe('#echo', function() { describe('#echo', function() {
it('should echo a string', function(done) { it('should echo a string', function(done) {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
var str = 'mystr'; var str = 'mystr';
api.echo(str, function(err, result) { api.echo(str, function(err, result) {
result.should.equal(str); result.should.equal(str);
@ -70,7 +76,9 @@ describe('API', function() {
describe('#echoNumber', function() { describe('#echoNumber', function() {
it('should echo a number', function(done) { it('should echo a number', function(done) {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
var num = 500; var num = 500;
api.echoNumber(num, function(err, result) { api.echoNumber(num, function(err, result) {
result.should.equal(num); result.should.equal(num);
@ -82,8 +90,12 @@ describe('API', function() {
describe('#echoObject', function() { describe('#echoObject', function() {
it('should echo an object', function(done) { it('should echo an object', function(done) {
var api = new API({Storage: Storage}); var api = new API({
var obj = {test:'test'}; Storage: Storage
});
var obj = {
test: 'test'
};
api.echoObject(obj, function(err, result) { api.echoObject(obj, function(err, result) {
result.test.should.equal(obj.test); result.test.should.equal(obj.test);
(typeof result).should.equal('object'); (typeof result).should.equal('object');
@ -94,7 +106,9 @@ describe('API', function() {
describe('#getArgTypes', function() { describe('#getArgTypes', function() {
it('should get the argTypes of echo', function(done) { it('should get the argTypes of echo', function(done) {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
api.getArgTypes('echo', function(err, result) { api.getArgTypes('echo', function(err, result) {
result[0][1].should.equal('string'); result[0][1].should.equal('string');
done(); done();
@ -104,7 +118,9 @@ describe('API', function() {
describe('#getCommands', function() { describe('#getCommands', function() {
it('should get all the commands', function(done) { it('should get all the commands', function(done) {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
var n = 0; var n = 0;
for (var i in api) for (var i in api)
@ -120,7 +136,9 @@ describe('API', function() {
describe('#getWallets', function() { describe('#getWallets', function() {
it('should get the wallet ids', function(done) { it('should get the wallet ids', function(done) {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
api.getWallets(function(err, result) { api.getWallets(function(err, result) {
result.length.should.be.greaterThan(-1); result.length.should.be.greaterThan(-1);
done(); done();
@ -130,7 +148,9 @@ describe('API', function() {
describe('#help', function() { describe('#help', function() {
it('should call _cmd_getCommands', function(done) { it('should call _cmd_getCommands', function(done) {
var api = new API({Storage: Storage}); var api = new API({
Storage: Storage
});
api._cmd_getCommands = function(callback) { api._cmd_getCommands = function(callback) {
(typeof arguments[0]).should.equal('function'); (typeof arguments[0]).should.equal('function');
callback(null, ['item']); callback(null, ['item']);

View file

@ -84,5 +84,3 @@ describe('AddressIndex model', function() {
}); });
}); });

View file

@ -21,5 +21,3 @@ describe('Passphrase model', function() {
}); });
}); });

View file

@ -31,7 +31,10 @@ var createW = function (networkName) {
} }
w.walletId = '1234567'; w.walletId = '1234567';
return {w:w, copayers: copayers}; return {
w: w,
copayers: copayers
};
}; };
describe('PublicKeyRing model', function() { describe('PublicKeyRing model', function() {
@ -63,7 +66,9 @@ describe('PublicKeyRing model', function() {
w2.registeredCopayers().should.equal(0); w2.registeredCopayers().should.equal(0);
w2.isComplete().should.equal(false); w2.isComplete().should.equal(false);
(function() {w2.getAddress(0, false);}).should.throw(); (function() {
w2.getAddress(0, false);
}).should.throw();
}); });
it('should add and check when adding shared pub keys', function() { it('should add and check when adding shared pub keys', function() {
@ -74,7 +79,9 @@ describe('PublicKeyRing model', function() {
w.isComplete().should.equal(true); w.isComplete().should.equal(true);
w.addCopayer.should.throw(); w.addCopayer.should.throw();
for (var i = 0; i < 5; i++) { for (var i = 0; i < 5; i++) {
(function() {w.addCopayer(copayers[i])}).should.throw(); (function() {
w.addCopayer(copayers[i])
}).should.throw();
} }
}); });
@ -100,7 +107,9 @@ describe('PublicKeyRing model', function() {
w2.isComplete().should.equal(true); w2.isComplete().should.equal(true);
w2.addCopayer.should.throw(); w2.addCopayer.should.throw();
for (var i = 0; i < 5; i++) { for (var i = 0; i < 5; i++) {
(function() {w.addCopayer(copayers[i])}).should.throw(); (function() {
w.addCopayer(copayers[i])
}).should.throw();
} }
w2.indexes.getChangeIndex().should.equal(changeN); w2.indexes.getChangeIndex().should.equal(changeN);
@ -194,29 +203,39 @@ describe('PublicKeyRing model', function() {
networkName: 'testnet', //wrong networkName: 'testnet', //wrong
walletId: w.walletId, walletId: w.walletId,
}); });
(function() { w2.merge(w);}).should.throw(); (function() {
w2.merge(w);
}).should.throw();
var w3 = new PublicKeyRing({ var w3 = new PublicKeyRing({
networkName: 'livenet', networkName: 'livenet',
walletId: w.walletId, walletId: w.walletId,
requiredCopayers: 2, // wrong requiredCopayers: 2, // wrong
}); });
(function() { w3.merge(w);}).should.throw(); (function() {
w3.merge(w);
}).should.throw();
var w4 = new PublicKeyRing({ var w4 = new PublicKeyRing({
networkName: 'livenet', networkName: 'livenet',
walletId: w.walletId, walletId: w.walletId,
totalCopayers: 3, // wrong totalCopayers: 3, // wrong
}); });
(function() { w4.merge(w);}).should.throw(); (function() {
w4.merge(w);
}).should.throw();
var w6 = new PublicKeyRing({ var w6 = new PublicKeyRing({
networkName: 'livenet', networkName: 'livenet',
}); });
(function() { w6.merge(w);}).should.throw(); (function() {
w6.merge(w);
}).should.throw();
w.networkName = 'livenet'; w.networkName = 'livenet';
(function() { w6.merge(w);}).should.throw(); (function() {
w6.merge(w);
}).should.throw();
var w0 = new PublicKeyRing({ var w0 = new PublicKeyRing({
@ -227,7 +246,9 @@ describe('PublicKeyRing model', function() {
w0.addCopayer(); w0.addCopayer();
w0.addCopayer(); w0.addCopayer();
w0.addCopayer(); w0.addCopayer();
(function() { w0.merge(w);}).should.throw(); (function() {
w0.merge(w);
}).should.throw();
w.merge(w0, true).should.equal(true); w.merge(w0, true).should.equal(true);
w.isComplete().should.equal(true); w.isComplete().should.equal(true);
@ -235,7 +256,9 @@ describe('PublicKeyRing model', function() {
networkName: 'livenet', networkName: 'livenet',
}); });
wx.addCopayer(); wx.addCopayer();
(function() { w.merge(wx);}).should.throw(); (function() {
w.merge(wx);
}).should.throw();
}); });
@ -370,5 +393,3 @@ describe('PublicKeyRing model', function() {
}); });
}); });

View file

@ -135,24 +135,45 @@ describe('Insight model', function() {
w.checkActivity(addresses, function(err, actives) { w.checkActivity(addresses, function(err, actives) {
console.log(err); console.log(err);
actives.length.should.equal(addresses.length); actives.length.should.equal(addresses.length);
actives.filter(function(i) { return i }).length.should.equal(0); actives.filter(function(i) {
return i
}).length.should.equal(0);
done(); done();
}); });
}); });
it('#checkActivity for active addreses', function(done) { it('#checkActivity for active addreses', function(done) {
var w = new Insight(); var w = new Insight();
w.getTransactions = function(addresses, cb) { w.getTransactions = function(addresses, cb) {
cb([ cb([{
{vin: [{ addr: '2NATQJnaQe2CUKLyhL1zdNkttJM1dUH9HaM'}], vout: []}, vin: [{
{vin: [{ addr: '2NATQJnaQe2CUKLyhL1zdNkttJM1dUH9HaM'}], vout: []}, addr: '2NATQJnaQe2CUKLyhL1zdNkttJM1dUH9HaM'
{vin: [{ addr: '2N9D5bcCQ2bPWUDByQ6Qb5bMgMtgsk1rw3x'}], vout: []}, }],
{vin: [], vout: [{scriptPubKey: {addresses: ['2NFjCBFZSsxiwWAD7CKQ3hzWFtf9DcqTucY']}}]} vout: []
]); }, {
vin: [{
addr: '2NATQJnaQe2CUKLyhL1zdNkttJM1dUH9HaM'
}],
vout: []
}, {
vin: [{
addr: '2N9D5bcCQ2bPWUDByQ6Qb5bMgMtgsk1rw3x'
}],
vout: []
}, {
vin: [],
vout: [{
scriptPubKey: {
addresses: ['2NFjCBFZSsxiwWAD7CKQ3hzWFtf9DcqTucY']
}
}]
}]);
}; };
w.checkActivity(addresses, function(err, actives) { w.checkActivity(addresses, function(err, actives) {
actives.length.should.equal(addresses.length); actives.length.should.equal(addresses.length);
actives.filter(function(i) { return i }).length.should.equal(3); actives.filter(function(i) {
return i
}).length.should.equal(3);
done(); done();
}); });
}); });

View file

@ -95,7 +95,9 @@ describe('Network / WebRTC', function() {
key.regenerateSync(); key.regenerateSync();
var copayerId = key.public.toString('hex'); var copayerId = key.public.toString('hex');
n._sendToOne = function(a1, a2, a3, cb) {cb();}; n._sendToOne = function(a1, a2, a3, cb) {
cb();
};
var sig = undefined; var sig = undefined;
n.send(copayerId, data, function() { n.send(copayerId, data, function() {
done(); done();
@ -138,7 +140,9 @@ describe('Network / WebRTC', function() {
key.regenerateSync(); key.regenerateSync();
var copayerIds = [key.public.toString('hex')]; var copayerIds = [key.public.toString('hex')];
n._sendToOne = function(a1, a2, a3, cb) {cb();}; n._sendToOne = function(a1, a2, a3, cb) {
cb();
};
var sig = undefined; var sig = undefined;
n.send(copayerIds, data, function() { n.send(copayerIds, data, function() {
done(); done();

View file

@ -17,12 +17,18 @@ describe('Storage/File', function() {
var fs = {} var fs = {}
fs.readFile = function(filename, callback) { fs.readFile = function(filename, callback) {
filename.should.equal('myfilename'); filename.should.equal('myfilename');
var obj = {"test":"test"}; var obj = {
"test": "test"
};
var encryptedStr = CryptoJS.AES.encrypt(JSON.stringify(obj), "password").toString(); var encryptedStr = CryptoJS.AES.encrypt(JSON.stringify(obj), "password").toString();
callback(null, encryptedStr); callback(null, encryptedStr);
}; };
var Storage = require('soop').load('../js/models/storage/File.js', {fs: fs}); var Storage = require('soop').load('../js/models/storage/File.js', {
var storage = new Storage({password: 'password'}); fs: fs
});
var storage = new Storage({
password: 'password'
});
storage.load('myfilename', function(err) { storage.load('myfilename', function(err) {
done(); done();
}); });
@ -36,8 +42,12 @@ describe('Storage/File', function() {
filename.should.equal('myfilename'); filename.should.equal('myfilename');
callback(); callback();
}; };
var Storage = require('soop').load('../js/models/storage/File.js', {fs: fs}); var Storage = require('soop').load('../js/models/storage/File.js', {
var storage = new Storage({password: 'password'}); fs: fs
});
var storage = new Storage({
password: 'password'
});
storage.save('myfilename', function(err) { storage.save('myfilename', function(err) {
done(); done();
}); });
@ -47,7 +57,11 @@ describe('Storage/File', function() {
describe('#_read', function() { describe('#_read', function() {
it('should return the value of a key', function() { it('should return the value of a key', function() {
var storage = new Storage(); var storage = new Storage();
storage.data = {'walletId':{'test':'data'}}; storage.data = {
'walletId': {
'test': 'data'
}
};
storage._read('walletId::test').should.equal('data'); storage._read('walletId::test').should.equal('data');
}); });
}); });
@ -68,7 +82,11 @@ describe('Storage/File', function() {
describe('#getGlobal', function() { describe('#getGlobal', function() {
it('should call storage._read', function() { it('should call storage._read', function() {
var storage = new Storage(); var storage = new Storage();
storage.data = {'walletId':{'test':'test'}}; storage.data = {
'walletId': {
'test': 'test'
}
};
storage._read = sinon.spy(); storage._read = sinon.spy();
storage.getGlobal('walletId::test'); storage.getGlobal('walletId::test');
storage._read.calledOnce.should.equal(true); storage._read.calledOnce.should.equal(true);
@ -91,7 +109,11 @@ describe('Storage/File', function() {
describe('#removeGlobal', function() { describe('#removeGlobal', function() {
it('should remove a global key', function(done) { it('should remove a global key', function(done) {
var storage = new Storage(); var storage = new Storage();
storage.data = {'walletId':{'key':'value'}}; storage.data = {
'walletId': {
'key': 'value'
}
};
storage.save = function(walletId, callback) { storage.save = function(walletId, callback) {
should.not.exist(storage.data[walletId]['key']); should.not.exist(storage.data[walletId]['key']);
callback(); callback();
@ -141,7 +163,9 @@ describe('Storage/File', function() {
describe('#setFromObj', function() { describe('#setFromObj', function() {
it('should set this object for a wallet', function(done) { it('should set this object for a wallet', function(done) {
var obj = {test:'testval'}; var obj = {
test: 'testval'
};
var storage = new Storage(); var storage = new Storage();
storage.save = function(walletId, callback) { storage.save = function(walletId, callback) {
callback(); callback();
@ -155,12 +179,16 @@ describe('Storage/File', function() {
describe('#getEncryptedObj', function() { describe('#getEncryptedObj', function() {
it('should give an encrypted object', function() { it('should give an encrypted object', function() {
var obj = {test:'testval'}; var obj = {
test: 'testval'
};
var data = JSON.stringify(obj); var data = JSON.stringify(obj);
var encrypted = CryptoJS.AES.encrypt(data, 'password'); var encrypted = CryptoJS.AES.encrypt(data, 'password');
var base64 = encrypted.toString(); var base64 = encrypted.toString();
var storage = new Storage({password: 'password'}); var storage = new Storage({
password: 'password'
});
storage.data['walletId'] = obj; storage.data['walletId'] = obj;
var enc = storage.getEncryptedObj('walletId'); var enc = storage.getEncryptedObj('walletId');

View file

@ -38,11 +38,17 @@ if (typeof process === 'undefined' || !process.version) {
1, 1000, -15, -1000, 1, 1000, -15, -1000,
0.1, -0.5, -0.5e-10, Math.PI, 0.1, -0.5, -0.5e-10, Math.PI,
'hi', 'auydoaiusyodaisudyoa', '0b5b8556a0c2ce828c9ccfa58b3dd0a1ae879b9b', 'hi', 'auydoaiusyodaisudyoa', '0b5b8556a0c2ce828c9ccfa58b3dd0a1ae879b9b',
'1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC', 'OP_DUP OP_HASH160 80ad90d4035', '1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC', 'OP_DUP OP_HASH160 80ad90d4035', [1, 2, 3, 4, 5, 6], {
[1,2,3,4,5,6], x: 1,
{ x: 1, y: 2}, y: 2
{ x: 'hi', y: null}, }, {
{ a: {}, b: [], c: [1,2,'hi']}, x: 'hi',
y: null
}, {
a: {},
b: [],
c: [1, 2, 'hi']
},
null null
]; ];
getSetData.forEach(function(obj) { getSetData.forEach(function(obj) {
@ -56,9 +62,13 @@ if (typeof process === 'undefined' || !process.version) {
describe('#export', function() { describe('#export', function() {
it('should export the encrypted wallet', function() { it('should export the encrypted wallet', function() {
var storage = new LocalEncrypted({password: 'password'}); var storage = new LocalEncrypted({
password: 'password'
});
storage.set(fakeWallet, timeStamp, 'testval'); storage.set(fakeWallet, timeStamp, 'testval');
var obj = {test:'testval'}; var obj = {
test: 'testval'
};
var encrypted = storage.export(obj); var encrypted = storage.export(obj);
encrypted.length.should.be.greaterThan(10); encrypted.length.should.be.greaterThan(10);
localStorage.removeItem(fakeWallet + '::' + timeStamp); localStorage.removeItem(fakeWallet + '::' + timeStamp);

View file

@ -55,6 +55,25 @@ describe("Unit: Controllers", function() {
}); });
}); });
describe('Setup Controller', function() {
var setupCtrl;
beforeEach(inject(function($controller, $rootScope) {
scope = $rootScope.$new();
setupCtrl = $controller('SetupController', {
$scope: scope,
});
}));
describe('#getNumber', function() {
it('should return an array of n undefined elements', function() {
var n = 5;
var array = scope.getNumber(n);
expect(array.length).equal(n);
});
});
});
describe('Address Controller', function() { describe('Address Controller', function() {
var addressCtrl; var addressCtrl;
beforeEach(inject(function($controller, $rootScope) { beforeEach(inject(function($controller, $rootScope) {
@ -109,10 +128,13 @@ describe("Unit: Controllers", function() {
); );
scope.model = { scope.model = {
newaddress: null, newaddress: null,
newlabel: null newlabel: null,
}; };
$compile(element)(scope); $compile(element)(scope);
$controller('SendController', {$scope: scope}); $controller('SendController', {
$scope: scope,
$modal: {},
});
scope.$digest(); scope.$digest();
form = scope.form; form = scope.form;
})); }));
@ -212,12 +234,20 @@ describe("Unit: Controllers", function() {
scope.$apply(); scope.$apply();
}); });
it('should return an array of n undefined elements', function() {
$httpBackend.flush(); // need flush
var n = 5;
var array = scope.getNumber(n);
expect(array.length).equal(n);
});
}); });
describe('Send Controller', function() { describe('Send Controller', function() {
var sendCtrl; var sendCtrl;
beforeEach(inject(function($controller, $rootScope) { beforeEach(inject(function($controller, $rootScope) {
scope = $rootScope.$new(); scope = $rootScope.$new();
$rootScope.availableBalance = 123456;
sendCtrl = $controller('SendController', { sendCtrl = $controller('SendController', {
$scope: scope, $scope: scope,
$modal: {}, $modal: {},
@ -227,6 +257,10 @@ describe("Unit: Controllers", function() {
it('should have a SendController', function() { it('should have a SendController', function() {
expect(scope.isMobile).not.to.equal(null); expect(scope.isMobile).not.to.equal(null);
}); });
it('should autotop balance correctly', function() {
scope.topAmount();
expect(scope.amount).to.equal(123356);
});
}); });
}); });

View file

@ -85,7 +85,11 @@ describe("Unit: Testing Directives", function() {
beforeEach(inject(function($compile, $rootScope) { beforeEach(inject(function($compile, $rootScope) {
$rootScope.wallet = { $rootScope.wallet = {
addressBook: {'2MtBXKLtZuXGDshUcyH6yq7aZ33Snbb49pT': {label: ':)'}} addressBook: {
'2MtBXKLtZuXGDshUcyH6yq7aZ33Snbb49pT': {
label: ':)'
}
}
} }
element1 = angular.element( element1 = angular.element(
'<contact address="2MtBXKLtZuXGDshUcyH6yq7aZ33Snbb49pT" />' '<contact address="2MtBXKLtZuXGDshUcyH6yq7aZ33Snbb49pT" />'

View file

@ -1,6 +1,71 @@
'use strict';
// //
// test/unit/filters/filtersSpec.js // test/unit/filters/filtersSpec.js
// //
describe("Unit: Testing Filters", function() { describe('Unit: Testing Filters', function() {
beforeEach(module('copayApp.filters'));
describe('limitAddress', function() {
it('should handle emtpy list', inject(function($filter) {
var limitAddress = $filter('limitAddress');
expect(limitAddress([], false)).to.be.empty;
}));
it('should honor show all', inject(function($filter) {
var limitAddress = $filter('limitAddress');
var addresses = [{}, {}, {}, {}, {}];
expect(limitAddress(addresses, true).length).to.equal(5);
expect(limitAddress([{}], false).length).to.equal(1);
}));
it('should filter correctly', inject(function($filter) {
var limitAddress = $filter('limitAddress');
var addresses = [{
isChange: true,
balance: 0
}, {
isChange: false,
balance: 0
}, {
isChange: true,
balance: 0
}, {
isChange: false,
balance: 0
}, {
isChange: true,
balance: 0
}, {
isChange: false,
balance: 0
}, {
isChange: true,
balance: 0
}, {
isChange: false,
balance: 0
}];
expect(limitAddress(addresses, false).length).to.equal(1);
addresses[0].isChange = false;
expect(limitAddress(addresses, false).length).to.equal(2);
addresses[2].isChange = false;
expect(limitAddress(addresses, false).length).to.equal(3);
addresses[3].isChange = false;
expect(limitAddress(addresses, false).length).to.equal(3);
addresses[0].balance = 20;
expect(limitAddress(addresses, false).length).to.equal(3);
addresses[0].balance = 20;
expect(limitAddress(addresses, false).length).to.equal(3);
addresses[7].balance = 20;
expect(limitAddress(addresses, false).length).to.equal(4);
}));
});
}); });