mirror of https://github.com/BTCPrivate/copay.git
Merge branch 'master' of github.com:bitpay/copay into feature/copay-shell
This commit is contained in:
commit
4dbad23eac
|
@ -103,6 +103,7 @@ var defaultConfig = {
|
||||||
totalCopayers: 3,
|
totalCopayers: 3,
|
||||||
spendUnconfirmed: 1,
|
spendUnconfirmed: 1,
|
||||||
verbose: 1,
|
verbose: 1,
|
||||||
|
reconnectDelay: 5000,
|
||||||
},
|
},
|
||||||
|
|
||||||
// blockchain service API config
|
// blockchain service API config
|
||||||
|
|
30
css/main.css
30
css/main.css
|
@ -30,6 +30,11 @@ html, body {height: 100%;}
|
||||||
box-shadow: inset 0px 0px 3px 0px rgba(0,0,0,0.10);
|
box-shadow: inset 0px 0px 3px 0px rgba(0,0,0,0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-gray.active {
|
||||||
|
color: #111 !important;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
#footer {
|
#footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
margin-top: -96px; /* negative value of footer height */
|
margin-top: -96px; /* negative value of footer height */
|
||||||
|
@ -59,7 +64,6 @@ html, body {height: 100%;}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
display: block;
|
display: block;
|
||||||
width: 130px;
|
|
||||||
height: 51px;
|
height: 51px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +173,7 @@ h3 {
|
||||||
border-right: 2px dashed #E3E3E3;
|
border-right: 2px dashed #E3E3E3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1025px) {
|
@media (max-width: 640px) {
|
||||||
.line-dashed-v {
|
.line-dashed-v {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
@ -347,11 +351,7 @@ hr { margin: 2.25rem 0;}
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-setup {
|
.box-setup {
|
||||||
padding: 20px 30px;
|
margin-bottom: 25px;
|
||||||
border: 1px solid #eee;
|
|
||||||
background: #fff;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-setup-copayers {
|
.box-setup-copayers {
|
||||||
|
@ -483,19 +483,6 @@ a.loading {
|
||||||
vertical-align:middle
|
vertical-align:middle
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
padding: 1.11111rem;
|
|
||||||
margin: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset legend {
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 0 0.16667rem;
|
|
||||||
margin: 0;
|
|
||||||
margin-left: -0.16667rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* notifications */
|
/* notifications */
|
||||||
|
|
||||||
.dr-notification-container {
|
.dr-notification-container {
|
||||||
|
@ -640,6 +627,7 @@ ul.pagination li.current a:hover, ul.pagination li.current a:focus {
|
||||||
background-size: 90px 44px !important;
|
background-size: 90px 44px !important;
|
||||||
float: left;
|
float: left;
|
||||||
margin-top: 0.7rem;
|
margin-top: 0.7rem;
|
||||||
|
width: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-content .small-9 {
|
.header-content .small-9 {
|
||||||
|
@ -668,4 +656,4 @@ ul.pagination li.current a:hover, ul.pagination li.current a:focus {
|
||||||
width: 71px;
|
width: 71px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,3 +321,7 @@ input.ng-invalid-wallet-secret {
|
||||||
color: #3FBC9C;
|
color: #3FBC9C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box-setup fieldset {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
115
index.html
115
index.html
|
@ -139,13 +139,13 @@
|
||||||
|
|
||||||
<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}">
|
||||||
<link rel="stylesheet" ng-href="{{theme}}">
|
<link rel="stylesheet" ng-href="{{theme}}">
|
||||||
<div class="row" ng-show="!$root.wallet">
|
<div ng-show="!$root.wallet">
|
||||||
<div class="large-12 columns text-right">
|
<div class="large-12 columns text-right">
|
||||||
Copay
|
Copay
|
||||||
<small>v{{version}}</small>
|
<small>v{{version}}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row p10t" ng-show="$root.wallet">
|
<div class="p10t" ng-show="$root.wallet">
|
||||||
<div class="large-3 medium-3 hide-for-small columns">
|
<div class="large-3 medium-3 hide-for-small columns">
|
||||||
<div>
|
<div>
|
||||||
<strong>{{$root.wallet.getName()}}</strong>
|
<strong>{{$root.wallet.getName()}}</strong>
|
||||||
|
@ -203,13 +203,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="!wallets.length">
|
<div ng-show="!wallets.length">
|
||||||
<h3>Create a new wallet</h3>
|
<h3>Create a new wallet</h3>
|
||||||
<form name="createForm" ng-submit="create(createForm)" novalidate>
|
|
||||||
<p class="text-gray">
|
<p class="text-gray">
|
||||||
Copay is a free, open-source, multisignature bitcoin wallet. A single-owner bitcoin wallet's security depends on carefully securing the private keys. With copay you can have multiple people controlling the funds, using bitcoin's multisignature functionality, requiring no trust in any third party.
|
Copay is a free, open-source, multisignature bitcoin wallet. A single-owner bitcoin wallet's security depends on carefully securing the private keys. With copay you can have multiple people controlling the funds, using bitcoin's multisignature functionality, requiring no trust in any third party.
|
||||||
</p>
|
</p>
|
||||||
<button type="submit" class="button secondary radius"
|
<a href="#setup" class="button secondary radius">Create</a>
|
||||||
ng-disabled="createForm.$invalid || loading" loading="Creating">Create</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -257,19 +254,21 @@
|
||||||
<label for="backupText" ng-click="pastetext=!pastetext" class="m10b">· Paste backup plain text code <i class="fi-clipboard"></i></label>
|
<label for="backupText" ng-click="pastetext=!pastetext" class="m10b">· Paste backup plain text code <i class="fi-clipboard"></i></label>
|
||||||
<textarea class="form-control" name="backupText" ng-model="backupText" rows="5" ng-show="pastetext"></textarea>
|
<textarea class="form-control" name="backupText" ng-model="backupText" rows="5" ng-show="pastetext"></textarea>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="large-8 medium-8 columns">
|
<div class="large-6 large-centered medium-6 medium-centered columns">
|
||||||
<label for="password">Password <small>Required</small></label>
|
<label for="password">Password <small>Required</small></label>
|
||||||
<input type="password" class="form-control" placeholder="Your wallet password" name="password" ng-model="password" required>
|
<input type="password" class="form-control" placeholder="Your wallet password" name="password" ng-model="password" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row line-dashed">
|
||||||
<div class="large-12 columns line-dashed">
|
<div class="large-6 medium-6 small-5 columns text-left">
|
||||||
|
<a class="button secondary radius" href="#signin">Go back</a>
|
||||||
|
</div>
|
||||||
|
<div class="large-6 medium-6 small-5 columns text-right">
|
||||||
<button type="submit" class="button primary radius right" ng-disabled="importForm.$invalid" loading="Importing">
|
<button type="submit" class="button primary radius right" ng-disabled="importForm.$invalid" loading="Importing">
|
||||||
Import backup
|
Import backup
|
||||||
</button>
|
</button>
|
||||||
<a class="button secondary radius" href="#signin">Go back</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -285,46 +284,64 @@
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="!loading">
|
<div ng-show="!loading">
|
||||||
<form name="setupForm" ng-submit="create(setupForm)" novalidate>
|
<form name="setupForm" ng-submit="create(setupForm)" novalidate>
|
||||||
<div class="small-12 medium-8 medium-centered large-8 large-centered columns box-setup">
|
<h3>Create new wallet</h3>
|
||||||
<h3>Create new wallet</h3>
|
|
||||||
<div class="large-6 columns line-dashed-v">
|
|
||||||
<h6>Select total number of copayers</h6>
|
|
||||||
<select ng-model="totalCopayers" ng-options="totalCopayers as totalCopayers for totalCopayers in TCValues">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="large-6 columns">
|
|
||||||
<h6>Select required signatures</h6>
|
|
||||||
<select ng-model="requiredCopayers" ng-options="requiredCopayers as requiredCopayers for requiredCopayers in RCValues">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m30v">
|
<div class="small-12 medium-8 medium-centered large-8 large-centered columns">
|
||||||
|
<label>Wallet name <small>Optional</small>
|
||||||
|
<input type="text" placeholder="Family vacation funds" class="form-control" ng-model="walletName">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="small-12 medium-8 medium-centered large-8 large-centered columns">
|
||||||
|
<div class="row">
|
||||||
|
<div class="small-12 medium-6 large-6 columns">
|
||||||
|
<label>Your name <small>Optional</small>
|
||||||
|
<input type="text" placeholder="Name" class="form-control" ng-model="myNickname">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
<input type="password" placeholder="Choose your password" class="form-control"
|
||||||
|
ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip="Password strength: {{passwordStrength}}" tooltip-trigger="focus" required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="small-12 medium-8 medium-centered large-8 large-centered columns box-setup">
|
||||||
|
<fieldset>
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-6 medium-6 columns line-dashed-v">
|
||||||
|
<label>Select total number of copayers
|
||||||
|
<select ng-model="totalCopayers" ng-options="totalCopayers as totalCopayers for totalCopayers in TCValues">
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="large-6 medium-6 columns">
|
||||||
|
<label>Select required signatures
|
||||||
|
<select ng-model="requiredCopayers" ng-options="requiredCopayers as requiredCopayers for requiredCopayers in RCValues">
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m10b">
|
||||||
<div class="box-setup-copayers">
|
<div class="box-setup-copayers">
|
||||||
<div class="box-setup-copayers-fix">
|
<div class="box-setup-copayers-fix">
|
||||||
<img class="box-setup-copay" ng-repeat="i in getNumber(totalCopayers) track by $index" src="./img/satoshi.gif" alt="Copayer {{$index+1}}-{{totalCopayers}}" ng-class="{'box-setup-copay-required': ($index+1) <= requiredCopayers}">
|
<img class="box-setup-copay" ng-repeat="i in getNumber(totalCopayers) track by $index" src="./img/satoshi.gif" alt="Copayer {{$index+1}}-{{totalCopayers}}" ng-class="{'box-setup-copay-required': ($index+1) <= requiredCopayers}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m30v">
|
|
||||||
<h6>Your Wallet Password<small>(doesn't need to be shared) Required</small></h6>
|
|
||||||
<input type="password" placeholder="Choose your password" class="form-control"
|
|
||||||
ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip="Password strength: {{passwordStrength}}" tooltip-trigger="focus" required>
|
|
||||||
</div>
|
|
||||||
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m30v">
|
|
||||||
<h6>Wallet name <small>Optional</small></h6>
|
|
||||||
<input type="text" placeholder="Family vacation funds" class="form-control" ng-model="walletName">
|
|
||||||
</div>
|
|
||||||
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m30v">
|
|
||||||
<h6>Your name <small>Optional</small></h6>
|
|
||||||
<input type="text" placeholder="Name" class="form-control" ng-model="myNickname">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="large-12 columns line-dashed">
|
|
||||||
<button type="submit" class="button primary radius right" ng-disabled="setupForm.$invalid || loading">
|
<div class="row line-dashed">
|
||||||
Create {{requiredCopayers}}-of-{{totalCopayers}} wallet
|
<div class="large-6 medium-6 small-5 columns text-left">
|
||||||
</button>
|
<a class="button secondary radius" href="#signin">Go back</a>
|
||||||
<a class="button secondary radius" href="#signin">Go back</a>
|
</div>
|
||||||
|
<div class="large-6 medium-6 small-7 columns text-right">
|
||||||
|
<button type="submit" class="button primary radius" ng-disabled="setupForm.$invalid || loading">
|
||||||
|
Create {{requiredCopayers}}-of-{{totalCopayers}} wallet
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -402,11 +419,11 @@
|
||||||
<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">
|
||||||
<h4> Transaction proposals <span ng-if="onlyPending">[Pending]</span> <small>({{txs.length}})</small></h4>
|
<h4> Transaction proposals <small>({{txs.length}})</small></h4>
|
||||||
|
|
||||||
<ul class="button-group radius">
|
<ul class="inline-list">
|
||||||
<li> <button class="secondary" ng-click="show(true)" ng-disabled="loading || onlyPending" loading="Updating"> Pending </button>
|
<li> <a class="text-gray size-12" ng-click="show(true)" ng-disabled="loading || onlyPending" loading="Updating" ng-class="{'active' : onlyPending}"> [ Pending ] </a> </li>
|
||||||
<li> <button class="secondary" ng-click="show()" ng-disabled="loading || !onlyPending" loading="Updating"> All </button>
|
<li> <a class="text-gray size-12" ng-click="show()" ng-disabled="loading || !onlyPending" loading="Updating" ng-class="{'active' : !onlyPending}"> [ All ] </a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="panel radius pending" ng-repeat="tx in txs | paged">
|
<div class="panel radius pending" ng-repeat="tx in txs | paged">
|
||||||
<div class="txheader row m10">
|
<div class="txheader row m10">
|
||||||
|
@ -501,8 +518,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
<h4>Last transactions</h4>
|
<h4>Last transactions</h4>
|
||||||
<a ng-click="toogleLast()" ng-disabled="loading" loading="Updating" ng-hide="lastShowed && !loading">Show</a>
|
<a class="size-12" ng-click="toogleLast()" ng-disabled="loading" loading="Updating" ng-hide="lastShowed && !loading">Show</a>
|
||||||
<a ng-click="toogleLast()" ng-disabled="loading" loading="Updating" ng-show="lastShowed && !loading">Hide</a>
|
<a class="size-12" ng-click="toogleLast()" ng-disabled="loading" loading="Updating" ng-show="lastShowed && !loading">Hide</a>
|
||||||
<div class="btransactions" ng-if="lastShowed">
|
<div class="btransactions" ng-if="lastShowed">
|
||||||
<div ng-if="!blockchain_txs[0].txid && !loading">
|
<div ng-if="!blockchain_txs[0].txid && !loading">
|
||||||
No transactions yet.
|
No transactions yet.
|
||||||
|
|
|
@ -20,8 +20,6 @@ angular.module('copay.header').controller('HeaderController',
|
||||||
'icon': 'fi-archive',
|
'icon': 'fi-archive',
|
||||||
'link': '#/backup'
|
'link': '#/backup'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
var beep = new Audio('sound/transaction.mp3');
|
|
||||||
|
|
||||||
$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); };
|
||||||
|
@ -54,6 +52,7 @@ angular.module('copay.header').controller('HeaderController',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentAddr) {
|
if (currentAddr) {
|
||||||
|
var beep = new Audio('sound/transaction.mp3');
|
||||||
$notification.funds('Received fund', currentAddr, receivedFund);
|
$notification.funds('Received fund', currentAddr, receivedFund);
|
||||||
beep.play();
|
beep.play();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ angular.module('copay.import').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;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,6 @@ angular.module('copay.signin').controller('SigninController',
|
||||||
$scope.selectedWalletId = $scope.wallets.length ? $scope.wallets[0].id : null;
|
$scope.selectedWalletId = $scope.wallets.length ? $scope.wallets[0].id : null;
|
||||||
$scope.openPassword = '';
|
$scope.openPassword = '';
|
||||||
|
|
||||||
$scope.create = function(form) {
|
|
||||||
$location.path('setup');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.open = function(form) {
|
$scope.open = function(form) {
|
||||||
if (form && form.$invalid) {
|
if (form && form.$invalid) {
|
||||||
$rootScope.$flashMessage = { message: 'Please, enter required fields', type: 'error'};
|
$rootScope.$flashMessage = { message: 'Please, enter required fields', type: 'error'};
|
||||||
|
|
|
@ -19,7 +19,8 @@ function Wallet(opts) {
|
||||||
//required params
|
//required params
|
||||||
['storage', 'network', 'blockchain',
|
['storage', 'network', 'blockchain',
|
||||||
'requiredCopayers', 'totalCopayers', 'spendUnconfirmed',
|
'requiredCopayers', 'totalCopayers', 'spendUnconfirmed',
|
||||||
'publicKeyRing', 'txProposals', 'privateKey', 'version'
|
'publicKeyRing', 'txProposals', 'privateKey', 'version',
|
||||||
|
'reconnectDelay'
|
||||||
].forEach(function(k) {
|
].forEach(function(k) {
|
||||||
if (typeof opts[k] === 'undefined')
|
if (typeof opts[k] === 'undefined')
|
||||||
throw new Error('missing required option for Wallet: ' + k);
|
throw new Error('missing required option for Wallet: ' + k);
|
||||||
|
@ -64,7 +65,7 @@ Wallet.prototype.seedCopayer = function(pubKey) {
|
||||||
Wallet.prototype.connectToAll = function() {
|
Wallet.prototype.connectToAll = function() {
|
||||||
|
|
||||||
var all = this.publicKeyRing.getAllCopayerIds();
|
var all = this.publicKeyRing.getAllCopayerIds();
|
||||||
console.log('[Wallet.js.58] connecting'); //TODO
|
console.log('[Wallet.js.58] connecting'); //TODO
|
||||||
this.network.connectToCopayers(all);
|
this.network.connectToCopayers(all);
|
||||||
if (this.seededCopayerId) {
|
if (this.seededCopayerId) {
|
||||||
this.sendWalletReady(this.seededCopayerId);
|
this.sendWalletReady(this.seededCopayerId);
|
||||||
|
@ -100,7 +101,7 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
|
||||||
var inTxp = copay.TxProposals.fromObj(data.txProposals);
|
var inTxp = copay.TxProposals.fromObj(data.txProposals);
|
||||||
var ids = inTxp.getNtxids();
|
var ids = inTxp.getNtxids();
|
||||||
|
|
||||||
if (ids.lenght>1) {
|
if (ids.lenght > 1) {
|
||||||
this.emit('badMessage', senderId);
|
this.emit('badMessage', senderId);
|
||||||
this.log('Received BAD TxProposal messsage FROM:', senderId); //TODO
|
this.log('Received BAD TxProposal messsage FROM:', senderId); //TODO
|
||||||
return;
|
return;
|
||||||
|
@ -164,12 +165,13 @@ Wallet.prototype._optsToObj = function() {
|
||||||
spendUnconfirmed: this.spendUnconfirmed,
|
spendUnconfirmed: this.spendUnconfirmed,
|
||||||
requiredCopayers: this.requiredCopayers,
|
requiredCopayers: this.requiredCopayers,
|
||||||
totalCopayers: this.totalCopayers,
|
totalCopayers: this.totalCopayers,
|
||||||
|
reconnectDelay: this.reconnectDelay,
|
||||||
name: this.name,
|
name: this.name,
|
||||||
netKey: this.netKey,
|
netKey: this.netKey,
|
||||||
version: this.version,
|
version: this.version,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.token){
|
if (this.token) {
|
||||||
obj.token = this.token;
|
obj.token = this.token;
|
||||||
obj.tokenTime = new Date().getTime();
|
obj.tokenTime = new Date().getTime();
|
||||||
}
|
}
|
||||||
|
@ -243,18 +245,26 @@ Wallet.prototype.netStart = function() {
|
||||||
net.start(startOpts, function() {
|
net.start(startOpts, function() {
|
||||||
self.emit('ready', net.getPeer());
|
self.emit('ready', net.getPeer());
|
||||||
self.token = net.peer.options.token;
|
self.token = net.peer.options.token;
|
||||||
setTimeout(function(){
|
setTimeout(function() {
|
||||||
console.log('[EMIT publicKeyRingUpdated:]'); //TODO
|
console.log('[EMIT publicKeyRingUpdated:]'); //TODO
|
||||||
self.emit('publicKeyRingUpdated', true);
|
self.emit('publicKeyRingUpdated', true);
|
||||||
console.log('[CONNECT:]'); //TODO
|
console.log('[CONNECT:]'); //TODO
|
||||||
self.connectToAll();
|
self.scheduleConnect();
|
||||||
console.log('[EMIT TxProposal]'); //TODO
|
console.log('[EMIT TxProposal]'); //TODO
|
||||||
self.emit('txProposalsUpdated');
|
self.emit('txProposalsUpdated');
|
||||||
self.store();
|
self.store();
|
||||||
},10);
|
}, 10);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.scheduleConnect = function() {
|
||||||
|
var self = this;
|
||||||
|
if (self.network.isOnline()) {
|
||||||
|
self.connectToAll();
|
||||||
|
setTimeout(self.scheduleConnect.bind(self), self.reconnectDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Wallet.prototype.getOnlinePeerIDs = function() {
|
Wallet.prototype.getOnlinePeerIDs = function() {
|
||||||
return this.network.getOnlinePeerIDs();
|
return this.network.getOnlinePeerIDs();
|
||||||
};
|
};
|
||||||
|
@ -331,7 +341,7 @@ Wallet.prototype.sendTxProposals = function(recipients, ntxid) {
|
||||||
|
|
||||||
var last = toSend[toSend];
|
var last = toSend[toSend];
|
||||||
|
|
||||||
for(var i in toSend) {
|
for (var i in toSend) {
|
||||||
var id = toSend[i];
|
var id = toSend[i];
|
||||||
var lastInBatch = (i == toSend.length - 1);
|
var lastInBatch = (i == toSend.length - 1);
|
||||||
this.network.send(recipients, {
|
this.network.send(recipients, {
|
||||||
|
@ -445,7 +455,7 @@ Wallet.prototype.sign = function(ntxid, cb) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
if (cb) return cb(ret);
|
if (cb) return cb(ret);
|
||||||
},10);
|
}, 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.sendTx = function(ntxid, cb) {
|
Wallet.prototype.sendTx = function(ntxid, cb) {
|
||||||
|
@ -625,7 +635,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
var selectedUtxos = b.getSelectedUnspent();
|
var selectedUtxos = b.getSelectedUnspent();
|
||||||
|
|
||||||
var inputChainPaths = selectedUtxos.map(function(utxo) {
|
var inputChainPaths = selectedUtxos.map(function(utxo) {
|
||||||
return pkr.pathForAddress(utxo.address);
|
return pkr.pathForAddress(utxo.address);
|
||||||
});
|
});
|
||||||
|
|
|
@ -115,6 +115,7 @@ WalletFactory.prototype.create = function(opts) {
|
||||||
opts.verbose = this.verbose;
|
opts.verbose = this.verbose;
|
||||||
|
|
||||||
opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed;
|
opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed;
|
||||||
|
opts.reconnectDelay = opts.reconnectDelay || this.walletDefaults.reconnectDelay;
|
||||||
opts.requiredCopayers = requiredCopayers;
|
opts.requiredCopayers = requiredCopayers;
|
||||||
opts.totalCopayers = totalCopayers;
|
opts.totalCopayers = totalCopayers;
|
||||||
opts.version = opts.version || this.version;
|
opts.version = opts.version || this.version;
|
||||||
|
@ -146,7 +147,6 @@ WalletFactory.prototype.open = function(walletId, opts) {
|
||||||
this.storage._setPassphrase(opts.passphrase);
|
this.storage._setPassphrase(opts.passphrase);
|
||||||
|
|
||||||
var w = this.read(walletId);
|
var w = this.read(walletId);
|
||||||
|
|
||||||
if (w) {
|
if (w) {
|
||||||
this._checkVersion(w.version);
|
this._checkVersion(w.version);
|
||||||
w.store();
|
w.store();
|
||||||
|
|
|
@ -313,8 +313,8 @@ Network.prototype.setCopayerId = function(copayerId) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO cache this.
|
||||||
Network.prototype.peerFromCopayer = function(hex) {
|
Network.prototype.peerFromCopayer = function(hex) {
|
||||||
// TODO cache this.
|
|
||||||
var SIN = bitcore.SIN;
|
var SIN = bitcore.SIN;
|
||||||
return new SIN(new Buffer(hex,'hex')).toString();
|
return new SIN(new Buffer(hex,'hex')).toString();
|
||||||
};
|
};
|
||||||
|
@ -409,6 +409,10 @@ Network.prototype.send = function(copayerIds, payload, cb) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Network.prototype.isOnline = function() {
|
||||||
|
return !!this.peer;
|
||||||
|
};
|
||||||
|
|
||||||
Network.prototype.connectTo = function(copayerId) {
|
Network.prototype.connectTo = function(copayerId) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
|
|
@ -15,37 +15,54 @@ module.exports = function(config) {
|
||||||
|
|
||||||
// list of files / patterns to load in the browser
|
// list of files / patterns to load in the browser
|
||||||
files: [
|
files: [
|
||||||
//3rd Party Code
|
//Configs
|
||||||
'lib/angular/angular.min.js',
|
'config.js',
|
||||||
'lib/angular-route/angular-route.js',
|
|
||||||
'lib/angular-mocks/angular-mocks.js',
|
|
||||||
'lib/bitcore.js',
|
|
||||||
'lib/socket.io.js',
|
|
||||||
|
|
||||||
//App-specific Code
|
'lib/angular/angular.min.js',
|
||||||
'js/*.js',
|
'lib/angular-mocks/angular-mocks.js',
|
||||||
'js/**/*.js',
|
'lib/moment/moment.js',
|
||||||
|
'lib/angular-moment/angular-moment.js',
|
||||||
|
'lib/qrcode-generator/js/qrcode.js',
|
||||||
|
'lib/angular-qrcode/qrcode.js',
|
||||||
|
'lib/angular-route/angular-route.min.js',
|
||||||
|
'lib/angular-foundation/mm-foundation.min.js',
|
||||||
|
'lib/angular-foundation/mm-foundation-tpls.min.js',
|
||||||
|
'lib/peer.js',
|
||||||
|
'lib/bitcore/browser/bundle.js',
|
||||||
|
'lib/crypto-js/rollups/sha256.js',
|
||||||
|
'lib/crypto-js/rollups/pbkdf2.js',
|
||||||
|
'lib/crypto-js/rollups/aes.js',
|
||||||
|
'lib/file-saver/FileSaver.js',
|
||||||
|
'lib/socket.io.js',
|
||||||
|
'lib/sjcl.js',
|
||||||
|
'lib/ios-imagefile-megapixel/megapix-image.js',
|
||||||
|
'lib/qrcode-decoder-js/lib/qrcode-decoder.min.js',
|
||||||
|
'js/copayBundle.js',
|
||||||
|
|
||||||
//Test-Specific Code
|
//Test-Specific Code
|
||||||
'lib/chai/chai.js',
|
'lib/chai/chai.js',
|
||||||
'test/lib/chai-should.js',
|
'test/lib/chai-should.js',
|
||||||
'test/lib/chai-expect.js',
|
'test/lib/chai-expect.js',
|
||||||
|
|
||||||
//Mocha stuff
|
//Mocha stuff
|
||||||
'test/mocha.conf.js',
|
'test/mocha.conf.js',
|
||||||
|
|
||||||
//Configs
|
|
||||||
'config.js',
|
|
||||||
|
|
||||||
//test files
|
//test files
|
||||||
'test/unit/**/*.js'
|
'test/unit/**/*.js',
|
||||||
|
|
||||||
|
//App-specific Code
|
||||||
|
'js/app.js',
|
||||||
|
'js/routes.js',
|
||||||
|
'js/directives.js',
|
||||||
|
'js/filters.js',
|
||||||
|
'js/services/*.js',
|
||||||
|
'js/controllers/*.js',
|
||||||
|
'js/init.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
// list of files to exclude
|
// list of files to exclude
|
||||||
exclude: [
|
exclude: [],
|
||||||
'js/models/**/*.js',
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
// preprocess matching files before serving them to the browser
|
// preprocess matching files before serving them to the browser
|
||||||
|
|
|
@ -7,8 +7,14 @@ function Network(opts) {
|
||||||
|
|
||||||
Network.parent=EventEmitter;
|
Network.parent=EventEmitter;
|
||||||
|
|
||||||
Network.prototype.start = function(openCallback, opts) {
|
Network.prototype.start = function(opts, cb) {
|
||||||
// start! :D
|
// start! :D
|
||||||
|
this.peer = {
|
||||||
|
options: {
|
||||||
|
token: "asd"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (cb) cb();
|
||||||
};
|
};
|
||||||
|
|
||||||
Network.prototype.send = function(peerIds, data, cb) {
|
Network.prototype.send = function(peerIds, data, cb) {
|
||||||
|
@ -24,4 +30,16 @@ Network.prototype.disconnect = function(cb) {
|
||||||
// disconect :c
|
// disconect :c
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Network.prototype.lockIncommingConnections = function() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Network.prototype.getPeer = function() {
|
||||||
|
};
|
||||||
|
Network.prototype.connectToCopayers = function(cps) {
|
||||||
|
};
|
||||||
|
Network.prototype.isOnline = function() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = require('soop')(Network);
|
module.exports = require('soop')(Network);
|
||||||
|
|
|
@ -2,14 +2,15 @@
|
||||||
|
|
||||||
var chai = chai || require('chai');
|
var chai = chai || require('chai');
|
||||||
var should = chai.should();
|
var should = chai.should();
|
||||||
|
var sinon = require('sinon');
|
||||||
var copay = copay || require('../copay');
|
var copay = copay || require('../copay');
|
||||||
var Wallet = require('../js/models/core/Wallet');
|
var Wallet = require('../js/models/core/Wallet');
|
||||||
var Storage= require('./mocks/FakeStorage');
|
var Storage = require('./mocks/FakeStorage');
|
||||||
var Network= require('./mocks/FakeNetwork');
|
var Network = require('./mocks/FakeNetwork');
|
||||||
var Blockchain= copay.Insight;
|
var Blockchain = copay.Insight;
|
||||||
|
|
||||||
var addCopayers = function (w) {
|
var addCopayers = function(w) {
|
||||||
for(var i=0; i<4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
w.publicKeyRing.addCopayer();
|
w.publicKeyRing.addCopayer();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -20,6 +21,7 @@ describe('Wallet model', function() {
|
||||||
requiredCopayers: 3,
|
requiredCopayers: 3,
|
||||||
totalCopayers: 5,
|
totalCopayers: 5,
|
||||||
spendUnconfirmed: 1,
|
spendUnconfirmed: 1,
|
||||||
|
reconnectDelay: 100,
|
||||||
blockchain: {
|
blockchain: {
|
||||||
host: 'test.insight.is',
|
host: 'test.insight.is',
|
||||||
port: 80
|
port: 80
|
||||||
|
@ -27,15 +29,20 @@ describe('Wallet model', function() {
|
||||||
networkName: 'testnet',
|
networkName: 'testnet',
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should fail to create an instance', function () {
|
it('should fail to create an instance', function() {
|
||||||
(function(){new Wallet(config)}).should.throw();
|
(function() {
|
||||||
|
new Wallet(config)
|
||||||
|
}).should.
|
||||||
|
throw ();
|
||||||
});
|
});
|
||||||
|
|
||||||
var createW = function (netKey) {
|
var createW = function(netKey) {
|
||||||
var c = JSON.parse(JSON.stringify(config));
|
var c = JSON.parse(JSON.stringify(config));
|
||||||
|
|
||||||
if (netKey) c.netKey = netKey;
|
if (netKey) c.netKey = netKey;
|
||||||
c.privateKey = new copay.PrivateKey({ networkName: c.networkName });
|
c.privateKey = new copay.PrivateKey({
|
||||||
|
networkName: c.networkName
|
||||||
|
});
|
||||||
|
|
||||||
c.publicKeyRing = new copay.PublicKeyRing({
|
c.publicKeyRing = new copay.PublicKeyRing({
|
||||||
networkName: c.networkName,
|
networkName: c.networkName,
|
||||||
|
@ -48,18 +55,18 @@ describe('Wallet model', function() {
|
||||||
c.txProposals = new copay.TxProposals({
|
c.txProposals = new copay.TxProposals({
|
||||||
networkName: c.networkName,
|
networkName: c.networkName,
|
||||||
});
|
});
|
||||||
c.storage = new Storage(config.storage);
|
c.storage = new Storage(config.storage);
|
||||||
c.network = new Network(config.network);
|
c.network = new Network(config.network);
|
||||||
c.blockchain = new Blockchain(config.blockchain);
|
c.blockchain = new Blockchain(config.blockchain);
|
||||||
|
|
||||||
c.networkName = config.networkName;
|
c.networkName = config.networkName;
|
||||||
c.verbose = config.verbose;
|
c.verbose = config.verbose;
|
||||||
c.version = '0.0.1';
|
c.version = '0.0.1';
|
||||||
|
|
||||||
return new Wallet(c);
|
return new Wallet(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should create an instance', function () {
|
it('should create an instance', function() {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
should.exist(w);
|
should.exist(w);
|
||||||
w.publicKeyRing.walletId.should.equal(w.id);
|
w.publicKeyRing.walletId.should.equal(w.id);
|
||||||
|
@ -70,11 +77,11 @@ describe('Wallet model', function() {
|
||||||
should.exist(w.privateKey);
|
should.exist(w.privateKey);
|
||||||
should.exist(w.txProposals);
|
should.exist(w.txProposals);
|
||||||
should.exist(w.netKey);
|
should.exist(w.netKey);
|
||||||
var b = new Buffer(w.netKey,'base64');
|
var b = new Buffer(w.netKey, 'base64');
|
||||||
b.toString('hex').length.should.equal(16);
|
b.toString('hex').length.should.equal(16);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should provide some basic features', function () {
|
it('should provide some basic features', function() {
|
||||||
var opts = {};
|
var opts = {};
|
||||||
var w = createW();
|
var w = createW();
|
||||||
addCopayers(w);
|
addCopayers(w);
|
||||||
|
@ -82,28 +89,26 @@ describe('Wallet model', function() {
|
||||||
w.publicKeyRing.isComplete().should.equal(true);
|
w.publicKeyRing.isComplete().should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
var unspentTest = [
|
var unspentTest = [{
|
||||||
{
|
|
||||||
"address": "dummy",
|
"address": "dummy",
|
||||||
"scriptPubKey": "dummy",
|
"scriptPubKey": "dummy",
|
||||||
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
||||||
"vout": 1,
|
"vout": 1,
|
||||||
"amount": 10,
|
"amount": 10,
|
||||||
"confirmations":7
|
"confirmations": 7
|
||||||
}
|
}];
|
||||||
];
|
|
||||||
|
|
||||||
var createW2 = function (privateKeys) {
|
var createW2 = function(privateKeys) {
|
||||||
var netKey = 'T0FbU2JLby0=';
|
var netKey = 'T0FbU2JLby0=';
|
||||||
var w = createW(netKey);
|
var w = createW(netKey);
|
||||||
should.exist(w);
|
should.exist(w);
|
||||||
|
|
||||||
var pkr = w.publicKeyRing;
|
var pkr = w.publicKeyRing;
|
||||||
|
|
||||||
for(var i=0; i<4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
if (privateKeys) {
|
if (privateKeys) {
|
||||||
var k=privateKeys[i];
|
var k = privateKeys[i];
|
||||||
pkr.addCopayer(k?k.deriveBIP45Branch().extendedPublicKeyString():null);
|
pkr.addCopayer(k ? k.deriveBIP45Branch().extendedPublicKeyString() : null);
|
||||||
} else {
|
} else {
|
||||||
pkr.addCopayer();
|
pkr.addCopayer();
|
||||||
}
|
}
|
||||||
|
@ -119,16 +124,16 @@ describe('Wallet model', function() {
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
it('#create, 1 sign', function () {
|
it('#create, 1 sign', function() {
|
||||||
|
|
||||||
var w = createW2();
|
var w = createW2();
|
||||||
|
|
||||||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
||||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
||||||
|
|
||||||
var ntxid = w.createTxSync(
|
var ntxid = w.createTxSync(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
unspentTest
|
unspentTest
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -141,30 +146,32 @@ describe('Wallet model', function() {
|
||||||
Object.keys(txp.signedBy).length.should.equal(1);
|
Object.keys(txp.signedBy).length.should.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#addressIsOwn', function () {
|
it('#addressIsOwn', function() {
|
||||||
var w = createW2();
|
var w = createW2();
|
||||||
var l = w.getAddressesStr();
|
var l = w.getAddressesStr();
|
||||||
for (var i=0; i<l.length; i++)
|
for (var i = 0; i < l.length; i++)
|
||||||
w.addressIsOwn(l[i]).should.equal(true);
|
w.addressIsOwn(l[i]).should.equal(true);
|
||||||
|
|
||||||
w.addressIsOwn(l[0], {excludeMain:true}).should.equal(false);
|
w.addressIsOwn(l[0], {
|
||||||
|
excludeMain: true
|
||||||
|
}).should.equal(false);
|
||||||
|
|
||||||
w.addressIsOwn('mmHqhvTVbxgJTnePa7cfweSRjBCy9bQQXJ').should.equal(false);
|
w.addressIsOwn('mmHqhvTVbxgJTnePa7cfweSRjBCy9bQQXJ').should.equal(false);
|
||||||
w.addressIsOwn('mgtUfP9sTJ6vPLoBxZLPEccGpcjNVryaCX').should.equal(false);
|
w.addressIsOwn('mgtUfP9sTJ6vPLoBxZLPEccGpcjNVryaCX').should.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#create. Signing with derivate keys', function () {
|
it('#create. Signing with derivate keys', function() {
|
||||||
|
|
||||||
var w = createW2();
|
var w = createW2();
|
||||||
|
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
for (var isChange=0; isChange<2; isChange++) {
|
for (var isChange = 0; isChange < 2; isChange++) {
|
||||||
for (var index=0; index<3; index++) {
|
for (var index = 0; index < 3; index++) {
|
||||||
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString();
|
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString();
|
||||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||||
w.createTxSync(
|
w.createTxSync(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
unspentTest
|
unspentTest
|
||||||
);
|
);
|
||||||
var t = w.txProposals;
|
var t = w.txProposals;
|
||||||
|
@ -174,13 +181,13 @@ describe('Wallet model', function() {
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
tx.countInputMissingSignatures(0).should.equal(2);
|
tx.countInputMissingSignatures(0).should.equal(2);
|
||||||
|
|
||||||
( t.txps[k].signedBy[w.privateKey.getId()] - ts > 0).should.equal(true);
|
(t.txps[k].signedBy[w.privateKey.getId()] - ts > 0).should.equal(true);
|
||||||
( t.txps[k].seenBy[w.privateKey.getId()] - ts > 0).should.equal(true);
|
(t.txps[k].seenBy[w.privateKey.getId()] - ts > 0).should.equal(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#fromObj #toObj round trip', function () {
|
it('#fromObj #toObj round trip', function() {
|
||||||
|
|
||||||
var w = createW2();
|
var w = createW2();
|
||||||
|
|
||||||
|
@ -188,9 +195,9 @@ describe('Wallet model', function() {
|
||||||
o = JSON.parse(JSON.stringify(o));
|
o = JSON.parse(JSON.stringify(o));
|
||||||
|
|
||||||
var w2 = Wallet.fromObj(o,
|
var w2 = Wallet.fromObj(o,
|
||||||
new Storage(config.storage),
|
new Storage(config.storage),
|
||||||
new Network(config.network),
|
new Network(config.network),
|
||||||
new Blockchain(config.blockchain));
|
new Blockchain(config.blockchain));
|
||||||
should.exist(w2);
|
should.exist(w2);
|
||||||
w2.publicKeyRing.requiredCopayers.should.equal(w.publicKeyRing.requiredCopayers);
|
w2.publicKeyRing.requiredCopayers.should.equal(w.publicKeyRing.requiredCopayers);
|
||||||
should.exist(w2.publicKeyRing.getCopayerId);
|
should.exist(w2.publicKeyRing.getCopayerId);
|
||||||
|
@ -198,21 +205,39 @@ describe('Wallet model', function() {
|
||||||
should.exist(w2.privateKey.toObj);
|
should.exist(w2.privateKey.toObj);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#getSecret decodeSecret', function () {
|
it('#getSecret decodeSecret', function() {
|
||||||
var w = createW2();
|
var w = createW2();
|
||||||
var id = w.getMyCopayerId();
|
var id = w.getMyCopayerId();
|
||||||
var nk = w.netKey;
|
var nk = w.netKey;
|
||||||
|
|
||||||
var sb= w.getSecret();
|
var sb = w.getSecret();
|
||||||
should.exist(sb);
|
should.exist(sb);
|
||||||
var s = Wallet.decodeSecret(sb);
|
var s = Wallet.decodeSecret(sb);
|
||||||
s.pubKey.should.equal(id);
|
s.pubKey.should.equal(id);
|
||||||
s.netKey.should.equal(nk);
|
s.netKey.should.equal(nk);
|
||||||
|
|
||||||
});
|
});
|
||||||
it('decodeSecret check', function () {
|
it('decodeSecret check', function() {
|
||||||
(function(){Wallet.decodeSecret('4fp61K187CsYmjoRQC5iAdC5eGmbCRsAAXfwEwetSQgHvZs27eWKaLaNHRoKM');}).should.not.throw();
|
(function() {
|
||||||
(function(){Wallet.decodeSecret('4fp61K187CsYmjoRQC5iAdC5eGmbCRsAAXfwEwetSQgHvZs27eWKaLaNHRoK');}).should.throw();
|
Wallet.decodeSecret('4fp61K187CsYmjoRQC5iAdC5eGmbCRsAAXfwEwetSQgHvZs27eWKaLaNHRoKM');
|
||||||
(function(){Wallet.decodeSecret('12345');}).should.throw();
|
}).should.not.
|
||||||
|
throw ();
|
||||||
|
(function() {
|
||||||
|
Wallet.decodeSecret('4fp61K187CsYmjoRQC5iAdC5eGmbCRsAAXfwEwetSQgHvZs27eWKaLaNHRoK');
|
||||||
|
}).should.
|
||||||
|
throw ();
|
||||||
|
(function() {
|
||||||
|
Wallet.decodeSecret('12345');
|
||||||
|
}).should.
|
||||||
|
throw ();
|
||||||
|
});
|
||||||
|
it('call reconnect after interval', function(done) {
|
||||||
|
var w = createW2();
|
||||||
|
var spy = sinon.spy(w, 'scheduleConnect');
|
||||||
|
w.netStart();
|
||||||
|
setTimeout(function() {
|
||||||
|
sinon.assert.callCount(spy, 10);
|
||||||
|
done();
|
||||||
|
}, 1000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,7 @@ describe('WalletFactory model', function() {
|
||||||
requiredCopayers: 3,
|
requiredCopayers: 3,
|
||||||
totalCopayers: 5,
|
totalCopayers: 5,
|
||||||
spendUnconfirmed: 1,
|
spendUnconfirmed: 1,
|
||||||
|
reconnectDelay: 100,
|
||||||
},
|
},
|
||||||
blockchain: {
|
blockchain: {
|
||||||
host: 'test.insight.is',
|
host: 'test.insight.is',
|
||||||
|
@ -60,7 +61,7 @@ describe('WalletFactory model', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#fromObj #toObj round trip', function() {
|
it('#fromObj #toObj round trip', function() {
|
||||||
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"netKey":"LppzFYqlgT0=","version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"changeAddressIndex":3,"addressIndex":3,"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}}}';
|
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"reconnectDelay":100,"netKey":"LppzFYqlgT0=","version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"changeAddressIndex":3,"addressIndex":3,"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}}}';
|
||||||
|
|
||||||
var wf = new WalletFactory(config, '0.0.5');
|
var wf = new WalletFactory(config, '0.0.5');
|
||||||
var w = wf.fromObj(JSON.parse(o));
|
var w = wf.fromObj(JSON.parse(o));
|
||||||
|
@ -75,9 +76,43 @@ describe('WalletFactory model', function() {
|
||||||
|
|
||||||
|
|
||||||
it('BIP32 length problem', function() {
|
it('BIP32 length problem', function() {
|
||||||
var sconfig = {"networkName":"testnet","network":{"key":"g23ihfh82h35rf","host":"162.242.219.26","port":10009,"path":"/","maxPeers":15,"debug":3},"limits":{"totalCopayers":10,"mPlusN":15},"wallet":{"requiredCopayers":2,"totalCopayers":3,"spendUnconfirmed":1,"verbose":0},"blockchain":{"host":"test.insight.is","port":3001},"socket":{"host":"test.insight.is","port":3001},"verbose":0,"themes":["default"]};
|
var sconfig = {
|
||||||
|
"networkName": "testnet",
|
||||||
|
"network": {
|
||||||
|
"key": "g23ihfh82h35rf",
|
||||||
|
"host": "162.242.219.26",
|
||||||
|
"port": 10009,
|
||||||
|
"path": "/",
|
||||||
|
"maxPeers": 15,
|
||||||
|
"debug": 3
|
||||||
|
},
|
||||||
|
"limits": {
|
||||||
|
"totalCopayers": 10,
|
||||||
|
"mPlusN": 15
|
||||||
|
},
|
||||||
|
"wallet": {
|
||||||
|
"requiredCopayers": 2,
|
||||||
|
"totalCopayers": 3,
|
||||||
|
"reconnectDelay":100,
|
||||||
|
"spendUnconfirmed": 1,
|
||||||
|
"verbose": 0
|
||||||
|
},
|
||||||
|
"blockchain": {
|
||||||
|
"host": "test.insight.is",
|
||||||
|
"port": 3001
|
||||||
|
},
|
||||||
|
"socket": {
|
||||||
|
"host": "test.insight.is",
|
||||||
|
"port": 3001
|
||||||
|
},
|
||||||
|
"verbose": 0,
|
||||||
|
"themes": ["default"]
|
||||||
|
};
|
||||||
var wf = new WalletFactory(sconfig, '0.0.1');
|
var wf = new WalletFactory(sconfig, '0.0.1');
|
||||||
var opts = {'requiredCopayers': 2, 'totalCopayers':3};
|
var opts = {
|
||||||
|
'requiredCopayers': 2,
|
||||||
|
'totalCopayers': 3
|
||||||
|
};
|
||||||
var w = wf.create(opts);
|
var w = wf.create(opts);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,4 +33,9 @@ describe("Unit: Testing Controllers", function() {
|
||||||
expect(copayApp.TransactionsController).not.to.equal(null);
|
expect(copayApp.TransactionsController).not.to.equal(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(angular.mock.module('copay.walletFactory'));
|
||||||
|
it('should display a link to create a new wallet if no wallets in localStorage', inject(function(walletFactory) {
|
||||||
|
expect(walletFactory.storage.getWalletIds()).to.be.empty;
|
||||||
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,10 +17,11 @@ describe("Unit: Testing Services", function() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
beforeEach(angular.mock.module('copay.controllerUtils'));
|
// TODO
|
||||||
|
/*beforeEach(angular.mock.module('copay.controllerUtils'));
|
||||||
|
|
||||||
it('should contain a controllerUtils service', inject(function(controllerUtils) {
|
it('should contain a controllerUtils service', inject(function(controllerUtils) {
|
||||||
expect(controllerUtils).not.to.equal(null);
|
expect(controllerUtils).not.to.equal(null);
|
||||||
}));
|
}));
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue