implement BITS + tests
This commit is contained in:
parent
ec859355c6
commit
727bf8524a
14 changed files with 213 additions and 79 deletions
|
|
@ -219,6 +219,14 @@ small.has-error {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.totalAmount {
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 120%;
|
||||||
|
margin-top:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.small {
|
.small {
|
||||||
font-size: 60%;
|
font-size: 60%;
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
|
|
|
||||||
51
index.html
51
index.html
|
|
@ -31,21 +31,19 @@
|
||||||
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:
|
Balance<br>
|
||||||
<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">{{totalBalance || 0}}
|
<span ng-if="!$root.updatingBalance" tooltip="{{totalBalanceBTC}} BTC" tooltip-trigger="mouseenter" tooltip-placement="bottom">{{totalBalance || 0 |number}} bits
|
||||||
<i class="fi-bitcoin"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="large-4 medium-4 columns">
|
<div class="large-4 medium-4 columns">
|
||||||
Available to Spend:
|
Available to Spend<br>
|
||||||
<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">{{availableBalance || 0}}
|
<span ng-show="!$root.updatingBalance" tooltip="{{availableBalanceBTC}} BTC" tooltip-trigger="mouseenter" tooltip-placement="bottom">{{availableBalance || 0|number}} bits
|
||||||
<i class="fi-bitcoin"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -383,13 +381,11 @@
|
||||||
<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">
|
<span ng-if="!$root.updatingBalance">
|
||||||
{{$root.balanceByAddr[addr.address] || 0}}
|
{{$root.balanceByAddr[addr.address] || 0|number}} bits
|
||||||
<i class="fi-bitcoin"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="addrWithFund != addr.address">
|
<span ng-if="addrWithFund != addr.address">
|
||||||
{{addr.balance || 0}}
|
{{addr.balance || 0|number}} bits
|
||||||
<i class="fi-bitcoin"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -407,14 +403,12 @@
|
||||||
<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">{{balanceByAddr[selectedAddr.address] || 0}}
|
<span ng-if="!$root.updatingBalance">{{balanceByAddr[selectedAddr.address] || 0 | number}}
|
||||||
<i class="fi-bitcoin"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="addrWithFund != selectedAddr.address" style="word-wrap: break-word;">
|
<span ng-if="addrWithFund != selectedAddr.address" style="word-wrap: break-word;">
|
||||||
{{selectedAddr.address}}<br/>
|
{{selectedAddr.address}}<br/>
|
||||||
{{selectedAddr.balance || 0}}
|
{{selectedAddr.balance || 0|number}} bits
|
||||||
<i class="fi-bitcoin"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</strong>
|
</strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -445,7 +439,7 @@
|
||||||
<div class="txheader row m10">
|
<div class="txheader row m10">
|
||||||
<div class="large-8 medium-8 small-12 columns">
|
<div class="large-8 medium-8 small-12 columns">
|
||||||
<div class="row" ng-repeat="out in tx.outs">
|
<div class="row" ng-repeat="out in tx.outs">
|
||||||
<div class="large-3 medium-3 small-3 columns ellipsis"> {{out.value}} <i class="fi-bitcoin size-18"></i></div>
|
<div class="large-3 medium-3 small-3 columns ellipsis"> {{out.value | number}} bits</div>
|
||||||
<div class="large-1 medium-1 small-2 columns fi-arrow-right size-24"> </div>
|
<div class="large-1 medium-1 small-2 columns fi-arrow-right size-24"> </div>
|
||||||
<div class="large-8 medium-8 small-7 columns ellipsis"> {{out.address}} </div>
|
<div class="large-8 medium-8 small-7 columns ellipsis"> {{out.address}} </div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -527,7 +521,7 @@
|
||||||
<p class="text-gray m5b" ng-show="!tx.finallyRejected && tx.missingSignatures>1">
|
<p class="text-gray m5b" ng-show="!tx.finallyRejected && tx.missingSignatures>1">
|
||||||
{{tx.missingSignatures}} signatures missing</p>
|
{{tx.missingSignatures}} signatures missing</p>
|
||||||
<div class="ellipsis small text-gray">
|
<div class="ellipsis small text-gray">
|
||||||
<strong>Fee:</strong> <i class="fi-bitcoin"></i> {{tx.fee}}
|
<strong>Fee:</strong> {{tx.fee|number}} bits
|
||||||
<strong>Proposal ID:</strong> {{tx.ntxid}}
|
<strong>Proposal ID:</strong> {{tx.ntxid}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -571,7 +565,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-5 medium-5 small-5 columns">
|
<div class="large-5 medium-5 small-5 columns">
|
||||||
<div ng-repeat="vin in btx.vinSimple">
|
<div ng-repeat="vin in btx.vinSimple">
|
||||||
<small class="right m5t">{{vin.value}}</small>
|
<small class="right m5t">{{vin.value| number}} bits</small>
|
||||||
<p class="ellipsis text-gray size-12"> {{vin.addr}} </p>
|
<p class="ellipsis text-gray size-12"> {{vin.addr}} </p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -580,7 +574,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="large-6 medium-6 small-6 columns">
|
<div class="large-6 medium-6 small-6 columns">
|
||||||
<div ng-repeat="vout in btx.voutSimple">
|
<div ng-repeat="vout in btx.voutSimple">
|
||||||
<small class="right m5t">{{vout.value}}</small>
|
<small class="right m5t">{{vout.value| number}} bits</small>
|
||||||
<p class="ellipsis text-gray size-12"> {{vout.addr}} </p>
|
<p class="ellipsis text-gray size-12"> {{vout.addr}} </p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -588,9 +582,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="m10 size-12 text-gray">
|
<div class="m10 size-12 text-gray">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-4 medium-4 small-4 columns">Fees: {{btx.fees}}</div>
|
<div class="large-4 medium-4 small-4 columns">Fees: {{btx.fees | number}} bits</div>
|
||||||
<div class="large-4 medium-4 small-4 columns text-center">Confirmations: {{btx.confirmations || 0}}</div>
|
<div class="large-4 medium-4 small-4 columns text-center">Confirmations: {{btx.confirmations || 0}}</div>
|
||||||
<div class="large-4 medium-4 small-4 columns text-right">Total: {{btx.valueOut}}</div>
|
<div class="large-4 medium-4 small-4 columns text-right">Total: {{btx.valueOut| number}} bits</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -661,13 +655,26 @@
|
||||||
<div class="small-9 columns">
|
<div class="small-9 columns">
|
||||||
<input type="number" id="amount" ng-disabled="loading"
|
<input type="number" id="amount" ng-disabled="loading"
|
||||||
name="amount" placeholder="Amount" ng-model="amount"
|
name="amount" placeholder="Amount" ng-model="amount"
|
||||||
min="0.0001" max="10000000" enough-amount required>
|
min="0.0001" max="10000000" enough-amount required
|
||||||
|
autocomplete="off"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="small-3 columns">
|
<div class="small-3 columns">
|
||||||
<span class="postfix">BTC</span>
|
<span class="postfix">bits</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="large-6 medium-6 columns m10t" ng-show="amount>0">
|
||||||
|
<small>
|
||||||
|
Total amount for this transaction:
|
||||||
|
</small>
|
||||||
|
<div class="totalAmount">
|
||||||
|
{{amount + defaultFee |number}}</b> bits
|
||||||
|
</div>
|
||||||
|
<small>
|
||||||
|
Including fee of {{defaultFee|number}} bits
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,7 @@ angular.module('copayApp.controllers').controller('ImportController',
|
||||||
}
|
}
|
||||||
$rootScope.wallet = w;
|
$rootScope.wallet = w;
|
||||||
|
|
||||||
controllerUtils.startNetwork($rootScope.wallet);
|
controllerUtils.startNetwork($rootScope.wallet, $scope);
|
||||||
$rootScope.wallet.on('connectionError', function() {
|
|
||||||
var message = "Looks like you are already connected to this wallet, please logout from it and try importing it again.";
|
|
||||||
$rootScope.$flashMessage = { message: message, type: 'error'};
|
|
||||||
});
|
|
||||||
$rootScope.wallet.on('serverError', function() {
|
|
||||||
$rootScope.$flashMessage = { message: 'The PeerJS server is not responding, please try again', type: 'error'};
|
|
||||||
controllerUtils.onErrorDigest();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,32 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('SendController',
|
angular.module('copayApp.controllers').controller('SendController',
|
||||||
function($scope, $rootScope, $window, $location, $timeout) {
|
function($scope, $rootScope, $window, $location, $timeout) {
|
||||||
$scope.title = 'Send';
|
$scope.title = 'Send';
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
|
$scope.defaultFee = bitcore.TransactionBuilder.FEE_PER_1000B_SAT / bitcore.util.BIT;
|
||||||
|
|
||||||
|
// TODO this shouldnt be on a particular controller.
|
||||||
// Detect mobile devices
|
// Detect mobile devices
|
||||||
var isMobile = {
|
var isMobile = {
|
||||||
Android: function() {
|
Android: function() {
|
||||||
return navigator.userAgent.match(/Android/i);
|
return navigator.userAgent.match(/Android/i);
|
||||||
},
|
},
|
||||||
BlackBerry: function() {
|
BlackBerry: function() {
|
||||||
return navigator.userAgent.match(/BlackBerry/i);
|
return navigator.userAgent.match(/BlackBerry/i);
|
||||||
},
|
},
|
||||||
iOS: function() {
|
iOS: function() {
|
||||||
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
|
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
|
||||||
},
|
},
|
||||||
Opera: function() {
|
Opera: function() {
|
||||||
return navigator.userAgent.match(/Opera Mini/i);
|
return navigator.userAgent.match(/Opera Mini/i);
|
||||||
},
|
},
|
||||||
Windows: function() {
|
Windows: function() {
|
||||||
return navigator.userAgent.match(/IEMobile/i);
|
return navigator.userAgent.match(/IEMobile/i);
|
||||||
},
|
},
|
||||||
any: function() {
|
any: function() {
|
||||||
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
|
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,27 +35,29 @@ angular.module('copayApp.controllers').controller('SendController',
|
||||||
|
|
||||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||||
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||||
|
|
||||||
$scope.isMobile = isMobile.any();
|
$scope.isMobile = isMobile.any();
|
||||||
$scope.unitIds = ['BTC','mBTC'];
|
|
||||||
$scope.selectedUnit = $scope.unitIds[0];
|
|
||||||
|
|
||||||
$scope.submitForm = function(form) {
|
$scope.submitForm = function(form) {
|
||||||
if (form.$invalid) {
|
if (form.$invalid) {
|
||||||
$rootScope.$flashMessage = { message: 'You can not send a proposal transaction. Please, try again', type: 'error'};
|
$rootScope.$flashMessage = {
|
||||||
|
message: 'You can not send a proposal transaction. Please, try again',
|
||||||
|
type: 'error'
|
||||||
|
};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
|
|
||||||
var address = form.address.$modelValue;
|
var address = form.address.$modelValue;
|
||||||
var amount = (form.amount.$modelValue * 100000000).toFixed(); // satoshi to string
|
var amount = (form.amount.$modelValue * 100) | 0;
|
||||||
var comment = form.comment.$modelValue;
|
|
||||||
|
|
||||||
var w = $rootScope.wallet;
|
var w = $rootScope.wallet;
|
||||||
w.createTx(address, amount, comment, function() {
|
w.createTx(address, amount, comment, function() {
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
$rootScope.$flashMessage = { message: 'The transaction proposal has been created', type: 'success'};
|
$rootScope.$flashMessage = {
|
||||||
|
message: 'The transaction proposal has been created',
|
||||||
|
type: 'success'
|
||||||
|
};
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -81,7 +86,11 @@ angular.module('copayApp.controllers').controller('SendController',
|
||||||
reader.onload = (function(theFile) {
|
reader.onload = (function(theFile) {
|
||||||
return function(e) {
|
return function(e) {
|
||||||
var mpImg = new MegaPixImage(file);
|
var mpImg = new MegaPixImage(file);
|
||||||
mpImg.render(canvas, { maxWidth: 200, maxHeight: 200, orientation: 6 });
|
mpImg.render(canvas, {
|
||||||
|
maxWidth: 200,
|
||||||
|
maxHeight: 200,
|
||||||
|
orientation: 6
|
||||||
|
});
|
||||||
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
qrcode.width = canvas.width;
|
qrcode.width = canvas.width;
|
||||||
|
|
@ -107,7 +116,7 @@ angular.module('copayApp.controllers').controller('SendController',
|
||||||
|
|
||||||
try {
|
try {
|
||||||
qrcode.decode();
|
qrcode.decode();
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
//qrcodeError(e);
|
//qrcodeError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +177,9 @@ angular.module('copayApp.controllers').controller('SendController',
|
||||||
canvas.height = 225;
|
canvas.height = 225;
|
||||||
context.clearRect(0, 0, 300, 225);
|
context.clearRect(0, 0, 300, 225);
|
||||||
|
|
||||||
navigator.getUserMedia({video: true}, _successCallback, _videoError);
|
navigator.getUserMedia({
|
||||||
|
video: true
|
||||||
|
}, _successCallback, _videoError);
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('TransactionsController',
|
angular.module('copayApp.controllers').controller('TransactionsController',
|
||||||
function($scope, $rootScope, $timeout, controllerUtils) {
|
function($scope, $rootScope, $timeout, controllerUtils) {
|
||||||
|
|
@ -10,8 +11,6 @@ angular.module('copayApp.controllers').controller('TransactionsController',
|
||||||
|
|
||||||
$scope.txpCurrentPage = 1;
|
$scope.txpCurrentPage = 1;
|
||||||
$scope.txpItemsPerPage = 4;
|
$scope.txpItemsPerPage = 4;
|
||||||
|
|
||||||
var COIN = 100000000;
|
|
||||||
$scope.blockchain_txs = [];
|
$scope.blockchain_txs = [];
|
||||||
|
|
||||||
$scope.update = function () {
|
$scope.update = function () {
|
||||||
|
|
@ -81,14 +80,14 @@ angular.module('copayApp.controllers').controller('TransactionsController',
|
||||||
tmp[addr].doubleSpentIndex = tmp[addr].doubleSpentIndex || items[i].doubleSpentIndex;
|
tmp[addr].doubleSpentIndex = tmp[addr].doubleSpentIndex || items[i].doubleSpentIndex;
|
||||||
tmp[addr].unconfirmedInput += items[i].unconfirmedInput;
|
tmp[addr].unconfirmedInput += items[i].unconfirmedInput;
|
||||||
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
|
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
|
||||||
tmp[addr].valueSat += Math.round(items[i].value * COIN);
|
tmp[addr].valueSat += (items[i].value * bitcore.util.COIN)|0;
|
||||||
tmp[addr].items.push(items[i]);
|
tmp[addr].items.push(items[i]);
|
||||||
tmp[addr].notAddr = notAddr;
|
tmp[addr].notAddr = notAddr;
|
||||||
tmp[addr].count++;
|
tmp[addr].count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
angular.forEach(tmp, function(v) {
|
angular.forEach(tmp, function(v) {
|
||||||
v.value = v.value || parseInt(v.valueSat) / COIN;
|
v.value = (v.valueSat|0) / bitcore.util.BIT;
|
||||||
ret.push(v);
|
ret.push(v);
|
||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -150,6 +149,8 @@ angular.module('copayApp.controllers').controller('TransactionsController',
|
||||||
for (var i=0; i<txs.length;i++) {
|
for (var i=0; i<txs.length;i++) {
|
||||||
txs[i].vinSimple = _aggregateItems(txs[i].vin);
|
txs[i].vinSimple = _aggregateItems(txs[i].vin);
|
||||||
txs[i].voutSimple = _aggregateItems(txs[i].vout);
|
txs[i].voutSimple = _aggregateItems(txs[i].vout);
|
||||||
|
txs[i].valueOut = ((txs[i].valueOut * bitcore.util.COIN)|0) / bitcore.util.BIT;
|
||||||
|
txs[i].fees = ((txs[i].fees * bitcore.util.COIN)|0) / bitcore.util.BIT;
|
||||||
$scope.blockchain_txs.push(txs[i]);
|
$scope.blockchain_txs.push(txs[i]);
|
||||||
}
|
}
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
|
|
|
||||||
|
|
@ -566,7 +566,8 @@ Wallet.prototype.getBalance = function(cb) {
|
||||||
var balance = 0;
|
var balance = 0;
|
||||||
var safeBalance = 0;
|
var safeBalance = 0;
|
||||||
var balanceByAddr = {};
|
var balanceByAddr = {};
|
||||||
var COIN = bitcore.util.COIN;
|
var BIT = coinUtil.BIT;
|
||||||
|
var COIN = coinUtil.COIN;
|
||||||
|
|
||||||
this.getUnspent(function(err, safeUnspent, unspent) {
|
this.getUnspent(function(err, safeUnspent, unspent) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -580,11 +581,11 @@ Wallet.prototype.getBalance = function(cb) {
|
||||||
balanceByAddr[u.address] = (balanceByAddr[u.address] || 0) + amt;
|
balanceByAddr[u.address] = (balanceByAddr[u.address] || 0) + amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we multiply and divide by COIN to avoid rounding errors when adding
|
// we multiply and divide by BIT to avoid rounding errors when adding
|
||||||
for (var a in balanceByAddr) {
|
for (var a in balanceByAddr) {
|
||||||
balanceByAddr[a] = balanceByAddr[a].toFixed(0) / COIN;
|
balanceByAddr[a] = balanceByAddr[a].toFixed(0) / BIT;
|
||||||
}
|
}
|
||||||
balance = balance / COIN;
|
balance = balance.toFixed(0) / BIT;
|
||||||
|
|
||||||
for (var i = 0; i < safeUnspent.length; i++) {
|
for (var i = 0; i < safeUnspent.length; i++) {
|
||||||
var u = safeUnspent[i];
|
var u = safeUnspent[i];
|
||||||
|
|
@ -592,7 +593,7 @@ Wallet.prototype.getBalance = function(cb) {
|
||||||
safeBalance += amt;
|
safeBalance += amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
safeBalance = safeBalance.toFixed(0) / COIN;
|
safeBalance = safeBalance.toFixed(0) /BIT ;
|
||||||
return cb(null, balance, balanceByAddr, safeBalance);
|
return cb(null, balance, balanceByAddr, safeBalance);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
|
||||||
angular.module('copayApp.services')
|
angular.module('copayApp.services')
|
||||||
.factory('controllerUtils', function($rootScope, $sce, $location, $notification, Socket, video) {
|
.factory('controllerUtils', function($rootScope, $sce, $location, $notification, $timeout, Socket, video) {
|
||||||
var root = {};
|
var root = {};
|
||||||
var bitcore = require('bitcore');
|
|
||||||
|
|
||||||
root.getVideoMutedStatus = function(copayer) {
|
root.getVideoMutedStatus = function(copayer) {
|
||||||
var vi = $rootScope.videoInfo[copayer]
|
var vi = $rootScope.videoInfo[copayer]
|
||||||
|
|
@ -106,11 +106,14 @@ angular.module('copayApp.services')
|
||||||
});
|
});
|
||||||
w.on('txProposalsUpdated', function(dontDigest) {
|
w.on('txProposalsUpdated', function(dontDigest) {
|
||||||
root.updateTxs({onlyPending:true});
|
root.updateTxs({onlyPending:true});
|
||||||
root.updateBalance(function(){
|
// give sometime to the tx to propagate.
|
||||||
if (!dontDigest) {
|
$timeout(function() {
|
||||||
$rootScope.$digest();
|
root.updateBalance(function(){
|
||||||
}
|
if (!dontDigest) {
|
||||||
});
|
$rootScope.$digest();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},3000);
|
||||||
});
|
});
|
||||||
w.on('connectionError', function(msg) {
|
w.on('connectionError', function(msg) {
|
||||||
root.onErrorDigest(null, msg);
|
root.onErrorDigest(null, msg);
|
||||||
|
|
@ -137,7 +140,6 @@ angular.module('copayApp.services')
|
||||||
var w = $rootScope.wallet;
|
var w = $rootScope.wallet;
|
||||||
if (!w) return root.onErrorDigest();
|
if (!w) return root.onErrorDigest();
|
||||||
|
|
||||||
|
|
||||||
$rootScope.balanceByAddr = {};
|
$rootScope.balanceByAddr = {};
|
||||||
$rootScope.updatingBalance = true;
|
$rootScope.updatingBalance = true;
|
||||||
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
||||||
|
|
@ -151,8 +153,10 @@ angular.module('copayApp.services')
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootScope.totalBalance = balance;
|
$rootScope.totalBalance = balance;
|
||||||
$rootScope.balanceByAddr = balanceByAddr;
|
$rootScope.totalBalanceBTC = (balance / 1e6).toFixed(3) ;
|
||||||
$rootScope.availableBalance = safeBalance;
|
$rootScope.availableBalance = safeBalance;
|
||||||
|
$rootScope.availableBalanceBTC = (safeBalance / 1e6).toFixed(3);
|
||||||
|
$rootScope.balanceByAddr = balanceByAddr;
|
||||||
root.updateAddressList();
|
root.updateAddressList();
|
||||||
$rootScope.updatingBalance = false;
|
$rootScope.updatingBalance = false;
|
||||||
return cb?cb():null;
|
return cb?cb():null;
|
||||||
|
|
@ -188,13 +192,13 @@ angular.module('copayApp.services')
|
||||||
if (!w.addressIsOwn(addr, {excludeMain:true})) {
|
if (!w.addressIsOwn(addr, {excludeMain:true})) {
|
||||||
outs.push({
|
outs.push({
|
||||||
address: addr,
|
address: addr,
|
||||||
value: bitcore.util.valueToBigInt(o.getValue())/bitcore.util.COIN,
|
value: bitcore.util.valueToBigInt(o.getValue())/bitcore.util.BIT,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// extra fields
|
// extra fields
|
||||||
i.outs = outs;
|
i.outs = outs;
|
||||||
i.fee = i.builder.feeSat/bitcore.util.COIN;
|
i.fee = i.builder.feeSat/bitcore.util.BIT;
|
||||||
i.missingSignatures = tx.countInputMissingSignatures(0);
|
i.missingSignatures = tx.countInputMissingSignatures(0);
|
||||||
txs.push(i);
|
txs.push(i);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,11 @@ module.exports = function(config) {
|
||||||
'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',
|
||||||
|
'test/mocks/FakeWallet.js',
|
||||||
|
|
||||||
//Mocha stuff
|
//Mocha stuff
|
||||||
'test/mocha.conf.js',
|
'test/mocha.conf.js',
|
||||||
|
|
||||||
|
|
||||||
//App-specific Code
|
//App-specific Code
|
||||||
'js/app.js',
|
'js/app.js',
|
||||||
'js/routes.js',
|
'js/routes.js',
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
var copay = require('copay');
|
var copay = require('copay');
|
||||||
</script>
|
</script>
|
||||||
<script src="test.blockchain.Insight.js"></script>
|
<script src="test.blockchain.Insight.js"></script>
|
||||||
<script src="test.performance.js"></script>
|
|
||||||
<script src="test.PrivateKey.js"></script>
|
<script src="test.PrivateKey.js"></script>
|
||||||
<script src="test.PublicKeyRing.js"></script>
|
<script src="test.PublicKeyRing.js"></script>
|
||||||
<script src="test.storage.LocalEncrypted.js"></script>
|
<script src="test.storage.LocalEncrypted.js"></script>
|
||||||
|
|
@ -26,6 +25,7 @@
|
||||||
<script src="test.TxProposals.js"></script>
|
<script src="test.TxProposals.js"></script>
|
||||||
<script src="test.Wallet.js"></script>
|
<script src="test.Wallet.js"></script>
|
||||||
<script src="test.Walletfactory.js"></script>
|
<script src="test.Walletfactory.js"></script>
|
||||||
|
<script src="test.performance.js"></script>
|
||||||
<!--
|
<!--
|
||||||
-->
|
-->
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ FakeBlockchain.prototype.getTransactions = function(addresses, cb) {
|
||||||
|
|
||||||
FakeBlockchain.prototype.fixUnspent = function(u) {
|
FakeBlockchain.prototype.fixUnspent = function(u) {
|
||||||
this.u = u;
|
this.u = u;
|
||||||
}
|
};
|
||||||
|
|
||||||
FakeBlockchain.prototype.getUnspent = function(addresses, cb) {
|
FakeBlockchain.prototype.getUnspent = function(addresses, cb) {
|
||||||
if (!addresses || !addresses.length) return cb(null, []);
|
if (!addresses || !addresses.length) return cb(null, []);
|
||||||
|
|
|
||||||
34
test/mocks/FakeWallet.js
Normal file
34
test/mocks/FakeWallet.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
var FakeWallet = function(){
|
||||||
|
this.balance=10000;
|
||||||
|
this.safeBalance=1000;
|
||||||
|
this.balanceByAddr={'1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC': 1000};
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeWallet.prototype.set = function(balance, safeBalance, balanceByAddr){
|
||||||
|
this.balance=balance;
|
||||||
|
this.safeBalance = safeBalance;
|
||||||
|
this.balanceByAddr = balanceByAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeWallet.prototype.getAddressesInfo=function(){
|
||||||
|
var ret = [];
|
||||||
|
|
||||||
|
for(var ii in this.balanceByAddr){
|
||||||
|
ret.push({
|
||||||
|
address: ii,
|
||||||
|
isChange: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FakeWallet.prototype.getBalance=function(cb){
|
||||||
|
return cb(null, this.balance, this.balanceByAddr, this.safeBalance);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This mock is meant for karma, module.exports is not necesary.
|
||||||
|
try {
|
||||||
|
module.exports = require('soop')(FakeWallet);
|
||||||
|
} catch (e) {}
|
||||||
|
|
@ -440,9 +440,65 @@ describe('Wallet model', function() {
|
||||||
r.length.should.equal(2);
|
r.length.should.equal(2);
|
||||||
r[0].should.not.equal(r[1]);
|
r[0].should.not.equal(r[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('#getBalance should call #getUnspent', function(done) {
|
||||||
|
var w = createW2();
|
||||||
|
var spy = sinon.spy(w.blockchain, 'getUnspent');
|
||||||
|
w.generateAddress();
|
||||||
|
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
||||||
|
sinon.assert.callCount(spy, 1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('#getBalance should return values in bits', function(done) {
|
||||||
|
var w = createW2();
|
||||||
|
w.generateAddress();
|
||||||
|
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
||||||
|
balance.should.equal(25000100.00);
|
||||||
|
safeBalance.should.equal(25000100.00);
|
||||||
|
balanceByAddr.mji7zocy8QzYywQakwWf99w9bCT6orY1C1.should.equal(25000100.00);
|
||||||
|
Object.keys(balanceByAddr).length.should.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var roundErrorChecks=[
|
||||||
|
{ unspent: [ 1.0001 ],
|
||||||
|
balance: 1000100
|
||||||
|
},
|
||||||
|
{ unspent: [ 1.0002 , 1.0003 , 1.0004 ],
|
||||||
|
balance: 3000900
|
||||||
|
},
|
||||||
|
{ unspent: [ 0.000002 , 1.000003 , 2.000004 ],
|
||||||
|
balance: 3000009
|
||||||
|
},
|
||||||
|
{ unspent: [ 0.0001 , 0.0003 ],
|
||||||
|
balance: 400
|
||||||
|
},
|
||||||
|
{ unspent: [ 0.0001 , 0.0003, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0002 ],
|
||||||
|
balance: 1100
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
roundErrorChecks.forEach(function(c){
|
||||||
|
it('check rounding errors '+ c.unspent[0], function(done) {
|
||||||
|
var w = createW2();
|
||||||
|
w.generateAddress();
|
||||||
|
w.blockchain.fixUnspent(c.unspent.map(function(u){return {amount:u}}));
|
||||||
|
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
||||||
|
balance.should.equal(c.balance);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should get balance', function(done) {
|
it('should get balance', function(done) {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
|
var spy = sinon.spy(w.blockchain, 'getUnspent');
|
||||||
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
w.getBalance(function(err, balance, balanceByAddr, safeBalance) {
|
||||||
|
sinon.assert.callCount(spy, 1);
|
||||||
balance.should.equal(0);
|
balance.should.equal(0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ describe("Unit: Controllers", function() {
|
||||||
expect(rootScope.insightError).equal(1);
|
expect(rootScope.insightError).equal(1);
|
||||||
scope.$apply();
|
scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
//
|
//
|
||||||
// test/unit/services/servicesSpec.js
|
// test/unit/services/servicesSpec.js
|
||||||
//
|
//
|
||||||
describe("Unit: Testing Services", function() {
|
describe("Unit: Socket Service", function() {
|
||||||
|
|
||||||
beforeEach(angular.mock.module('copayApp.services'));
|
beforeEach(angular.mock.module('copayApp.services'));
|
||||||
|
|
||||||
it('should contain a Socket service', inject(function(Socket) {
|
it('should contain a Socket service', inject(function(Socket) {
|
||||||
|
|
@ -17,7 +16,7 @@ describe("Unit: Testing Services", function() {
|
||||||
|
|
||||||
it('Socket should support #sysOn', inject(function(Socket) {
|
it('Socket should support #sysOn', inject(function(Socket) {
|
||||||
expect(Socket.sysOn).to.be.a('function');
|
expect(Socket.sysOn).to.be.a('function');
|
||||||
}))
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('Socket should add handlers with #on', inject(function(Socket) {
|
it('Socket should add handlers with #on', inject(function(Socket) {
|
||||||
|
|
@ -40,19 +39,39 @@ describe("Unit: Testing Services", function() {
|
||||||
ret = Socket.getListeners();
|
ret = Socket.getListeners();
|
||||||
expect(Object.keys(ret)).to.have.length(0);
|
expect(Object.keys(ret)).to.have.length(0);
|
||||||
}));
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("Unit: Walletfactory Service", function() {
|
||||||
|
beforeEach(angular.mock.module('copayApp.services'));
|
||||||
it('should contain a walletFactory service', inject(function(walletFactory) {
|
it('should contain a walletFactory service', inject(function(walletFactory) {
|
||||||
expect(walletFactory).not.to.equal(null);
|
expect(walletFactory).not.to.equal(null);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
/*beforeEach(angular.mock.module('copayApp.controllerUtils'));
|
|
||||||
|
|
||||||
it('should contain a controllerUtils service', inject(function(controllerUtils) {
|
|
||||||
expect(controllerUtils).not.to.equal(null);
|
|
||||||
}));
|
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Unit: controllerUtils", function() {
|
||||||
|
beforeEach(angular.mock.module('copayApp.services'));
|
||||||
|
beforeEach(angular.mock.module('notifications'));
|
||||||
|
|
||||||
|
it('should updateBalance in bits', inject(function(controllerUtils, $rootScope) {
|
||||||
|
expect(controllerUtils.updateBalance).not.to.equal(null);
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
|
||||||
|
$rootScope.wallet=new FakeWallet();
|
||||||
|
var addr = '1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC';
|
||||||
|
var a = {}; a[addr]=100;
|
||||||
|
$rootScope.wallet.set(1000000,900000,a);
|
||||||
|
|
||||||
|
controllerUtils.updateBalance(function() {
|
||||||
|
expect($rootScope.totalBalance).to.be.equal(1000000);
|
||||||
|
expect($rootScope.totalBalanceBTC).to.be.equal('1.000');
|
||||||
|
expect($rootScope.availableBalance).to.be.equal(900000);
|
||||||
|
expect($rootScope.availableBalanceBTC).to.be.equal('0.900');
|
||||||
|
expect($rootScope.addrInfos).not.to.equal(null);
|
||||||
|
expect($rootScope.addrInfos[0].address).to.equal(addr);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue