From b221bb16d42040cfa953faa39ac952ce870cae3d Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 25 Jun 2014 15:24:11 -0300 Subject: [PATCH 01/30] Minor fixes: * min value allowed on input (was 1, now is 0.0001) * Number filter with 4 decimals --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index e7825c84c..0ac3f6cfd 100644 --- a/index.html +++ b/index.html @@ -688,7 +688,7 @@
@@ -702,13 +702,13 @@ Total amount for this transaction:
- {{amount + defaultFee |number}} {{$root.unitName}} + {{amount + defaultFee |number:4}} {{$root.unitName}} - {{ ((amount + defaultFee) * unitToBtc) |number}} BTC + {{ ((amount + defaultFee) * unitToBtc) |number:4}} BTC
- Including fee of {{defaultFee|number}} {{$root.unitName}} + Including fee of {{defaultFee |number:4}} {{$root.unitName}} From f379ee95c02fc07609bb04b7d553bd3982281577 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 25 Jun 2014 15:44:19 -0300 Subject: [PATCH 02/30] Fixes: number variables forced to be a Number type. --- js/directives.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/directives.js b/js/directives.js index 586a1ac31..fac694ddb 100644 --- a/js/directives.js +++ b/js/directives.js @@ -40,12 +40,12 @@ angular.module('copayApp.directives') .directive('enoughAmount', ['$rootScope', function($rootScope) { var bitcore = require('bitcore'); - var feeSat = bitcore.TransactionBuilder.FEE_PER_1000B_SAT; + var feeSat = Number(bitcore.TransactionBuilder.FEE_PER_1000B_SAT); return { require: 'ngModel', link: function(scope, element, attrs, ctrl) { var val = function(value) { - var availableBalanceNum = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0); + var availableBalanceNum = Number(($rootScope.availableBalance * config.unitToSatoshi).toFixed(0)); var vNum = Number((value * config.unitToSatoshi).toFixed(0)) + feeSat; if (typeof vNum == "number" && vNum > 0) { if (availableBalanceNum < vNum) { From 96cbf8ad7bb5ebd79823808d56f6b749e801d7e1 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Wed, 25 Jun 2014 15:49:02 -0300 Subject: [PATCH 03/30] Add feedback while importing wallet --- index.html | 2 +- js/controllers/import.js | 15 ++++++++++++++- js/models/core/Wallet.js | 1 + js/models/core/WalletFactory.js | 1 + test/test.Wallet.js | 2 +- 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index e7825c84c..52739204e 100644 --- a/index.html +++ b/index.html @@ -276,7 +276,7 @@
- Importing wallet... + {{ importStatus }}

{{title}}

diff --git a/js/controllers/import.js b/js/controllers/import.js index c3401862b..4ba9d0d0d 100644 --- a/js/controllers/import.js +++ b/js/controllers/import.js @@ -3,10 +3,19 @@ angular.module('copayApp.controllers').controller('ImportController', function($scope, $rootScope, walletFactory, controllerUtils, Passphrase) { $scope.title = 'Import a backup'; + $scope.importStatus = 'Importing wallet - Reading backup...'; + var reader = new FileReader(); + + var updateStatus = function(status) { + $scope.importStatus = status; + $scope.$digest(); + } + var _importBackup = function(encryptedObj) { Passphrase.getBase64Async($scope.password, function(passphrase) { - walletFactory.import(encryptedObj, passphrase, function(err, w) { + updateStatus('Importing wallet - Setting things up...'); + var w = walletFactory.import(encryptedObj, passphrase, function(err, w) { if (err) { $scope.loading = false; $rootScope.$flashMessage = { @@ -19,6 +28,10 @@ angular.module('copayApp.controllers').controller('ImportController', $rootScope.wallet = w; controllerUtils.startNetwork($rootScope.wallet, $scope); }); + + w.on('updatingIndexes', function(){ + updateStatus('Importing wallet - We are almost there...'); + }); }); }; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 0bfa3dcf4..a87ab10d1 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -755,6 +755,7 @@ Wallet.prototype.updateIndexes = function(callback) { if (changeIndex != -1) self.publicKeyRing.indexes.changeIndex = changeIndex + 1; + self.emit('updatingIndexes'); start = self.publicKeyRing.indexes.receiveIndex; self.indexDiscovery(start, false, 20, function(err, receiveIndex) { if (err) return callback(err); diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 03d59e2ea..35a574ebd 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -84,6 +84,7 @@ WalletFactory.prototype.import = function(base64, password, cb) { self.log('Indexes updated'); cb(null, w); }); + return w; } WalletFactory.prototype.read = function(walletId) { diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 14a7ee490..17f8b3901 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -743,7 +743,7 @@ describe('Wallet model', function() { var spyEmit = sinon.spy(w, 'emit'); w.updateIndexes(function(err) { sinon.assert.callCount(spyStore, 1); - sinon.assert.callCount(spyEmit, 1); + sinon.assert.callCount(spyEmit, 2); done(); }); }); From db59a1bd36ecea97dd8a5d50bdb482f173741fe9 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Wed, 25 Jun 2014 16:17:34 -0300 Subject: [PATCH 04/30] reduce the chance of a test failure --- test/test.Wallet.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 17f8b3901..ff8631ebe 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -331,7 +331,6 @@ describe('Wallet model', function() { var w = cachedCreateW2(); var spy = sinon.spy(w, 'scheduleConnect'); var callCount = 3; - w.reconnectDelay = 25; w.netStart(); setTimeout(function() { sinon.assert.callCount(spy, callCount); From c669fc2d17c7794ed4e9151f36c09336cfc0e3b2 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 25 Jun 2014 17:10:00 -0300 Subject: [PATCH 05/30] More tests for amounts validation --- test/unit/directives/directivesSpec.js | 114 ++++++++++++++++++------- test/unit/services/servicesSpec.js | 6 ++ 2 files changed, 89 insertions(+), 31 deletions(-) diff --git a/test/unit/directives/directivesSpec.js b/test/unit/directives/directivesSpec.js index 882939143..ff3efc4a8 100644 --- a/test/unit/directives/directivesSpec.js +++ b/test/unit/directives/directivesSpec.js @@ -8,6 +8,10 @@ describe("Unit: Testing Directives", function() { beforeEach(module('copayApp.directives')); + beforeEach(function() { + config.unitToSatoshi = 100; + config.unitName = 'bits'; + }); describe('Check config', function() { it('unit should be set to BITS in config.js', function() { @@ -43,41 +47,89 @@ describe("Unit: Testing Directives", function() { }); describe('Validate Amount', function() { - beforeEach(inject(function($compile, $rootScope) { - $scope = $rootScope; - $rootScope.availableBalance = 1000; - var element = angular.element( - '
' + - '' + - '
' - ); - $scope.model = { - amount: null - }; - $compile(element)($scope); - $scope.$digest(); - form = $scope.form; - })); + describe('Unit: bits', function() { + beforeEach(inject(function($compile, $rootScope) { + $scope = $rootScope; + $rootScope.availableBalance = 1000; + var element = angular.element( + '
' + + '' + + '
' + ); + $scope.model = { + amount: null + }; + $compile(element)($scope); + $scope.$digest(); + form = $scope.form; + })); + it('should validate', function() { + form.amount.$setViewValue(100); + expect(form.amount.$invalid).to.equal(false); + form.amount.$setViewValue(800); + expect(form.amount.$invalid).to.equal(false); + form.amount.$setViewValue(900); + expect($scope.notEnoughAmount).to.equal(null); + }); - - - it('should validate', function() { - form.amount.$setViewValue(100); - expect(form.amount.$invalid).to.equal(false); - form.amount.$setViewValue(900); - expect(form.amount.$invalid).to.equal(false); + it('should not validate', function() { + form.amount.$setViewValue(0); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(9999999999); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(901); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(1000); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(901); + expect($scope.notEnoughAmount).to.equal(true); + }); }); - it('should not validate', function() { - form.amount.$setViewValue(0); - expect(form.amount.$invalid).to.equal(true); - form.amount.$setViewValue(9999999999); - expect(form.amount.$invalid).to.equal(true); - form.amount.$setViewValue(901); - expect(form.amount.$invalid).to.equal(true); - form.amount.$setViewValue(1000); - expect(form.amount.$invalid).to.equal(true); + describe('Unit: BTC', function() { + beforeEach(inject(function($compile, $rootScope) { + config.unitToSatoshi = 100000000; + config.unitName = 'BTC'; + $scope = $rootScope; + $rootScope.availableBalance = 0.04; + var element = angular.element( + '
' + + '' + + '
' + ); + $scope.model = { + amount: null + }; + $compile(element)($scope); + $scope.$digest(); + form = $scope.form; + })); + + it('should validate', function() { + form.amount.$setViewValue(0.01); + expect($scope.notEnoughAmount).to.equal(null); + expect(form.amount.$invalid).to.equal(false); + form.amount.$setViewValue(0.039); + expect($scope.notEnoughAmount).to.equal(null); + expect(form.amount.$invalid).to.equal(false); + }); + + it('should not validate', function() { + form.amount.$setViewValue(0.03999); + expect($scope.notEnoughAmount).to.equal(true); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(0); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(0.0); + expect(form.amount.$invalid).to.equal(true); + form.amount.$setViewValue(0.05); + expect($scope.notEnoughAmount).to.equal(true); + expect(form.amount.$invalid).to.equal(true); + + }); + }); + }); describe('Contact directive', function() { diff --git a/test/unit/services/servicesSpec.js b/test/unit/services/servicesSpec.js index 388007e06..2c29c78ea 100644 --- a/test/unit/services/servicesSpec.js +++ b/test/unit/services/servicesSpec.js @@ -5,7 +5,13 @@ // var sinon = require('sinon'); +beforeEach(function() { + config.unitToSatoshi = 100; + config.unitName = 'bits'; +}); + describe('Check config', function() { + it('unit should be set to BITS in config.js', function() { expect(config.unitToSatoshi).to.equal(100); expect(config.unitName).to.equal('bits'); From 2de90d093e08fdf5a00ccf34cd5f892d1492dd9a Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 25 Jun 2014 18:54:08 -0300 Subject: [PATCH 06/30] Fixes: * Copy available funds to input (amount) on Chrome browser. * Improve style of topAvailable button. * Show valid message immediately after copy. * Hide link if not have funds --- css/main.css | 6 ++++++ index.html | 6 +++++- js/controllers/send.js | 10 +++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/css/main.css b/css/main.css index 5c748b33f..2aeac8172 100644 --- a/css/main.css +++ b/css/main.css @@ -635,3 +635,9 @@ ul.pagination li.current a:hover, ul.pagination li.current a:focus { color:white; } +.input-note { + margin-top: -10px; + display: block; + margin-bottom: 1rem; +} + diff --git a/index.html b/index.html index 0ac3f6cfd..8d162de99 100644 --- a/index.html +++ b/index.html @@ -678,7 +678,6 @@
{{$root.unitName}} diff --git a/js/controllers/send.js b/js/controllers/send.js index 26c50f6aa..9d4e96cb3 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -267,8 +267,12 @@ 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; + $scope.getAvailableAmount = function() { + return ((($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT) / config.unitToSatoshi); + }; + + $scope.topAmount = function(form) { + $scope.amount = $scope.getAvailableAmount(); + form.amount.$pristine = false; }; }); From e330da0b9b651b78e23e999c45a1a356d86d0c34 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 25 Jun 2014 19:11:50 -0300 Subject: [PATCH 07/30] Fixed test and new test entry for new method --- test/unit/controllers/controllersSpec.js | 26 +++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index 5c8dd6ed8..03de6ccf6 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -283,10 +283,23 @@ describe("Unit: Controllers", function() { }); describe('Send Controller', function() { - var sendCtrl; - beforeEach(inject(function($controller, $rootScope) { + var sendCtrl, form; + beforeEach(inject(function($compile, $rootScope, $controller) { scope = $rootScope.$new(); $rootScope.availableBalance = 123456; + + var element = angular.element( + '
' + + '' + + '
' + ); + scope.model = { + amount: null + }; + $compile(element)(scope); + scope.$digest(); + form = scope.form; + sendCtrl = $controller('SendController', { $scope: scope, $modal: {}, @@ -297,8 +310,15 @@ describe("Unit: Controllers", function() { expect(scope.isMobile).not.to.equal(null); }); it('should autotop balance correctly', function() { - scope.topAmount(); + scope.topAmount(form); + form.amount.$setViewValue(123356); expect(scope.amount).to.equal(123356); + expect(form.amount.$invalid).to.equal(false); + expect(form.amount.$pristine).to.equal(false); + }); + it('should return available amount', function() { + var amount = scope.getAvailableAmount(); + expect(amount).to.equal(123356); }); }); From a5a30c3ba56038b1c1479f75e4c305431dc0930d Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 26 Jun 2014 10:08:40 -0300 Subject: [PATCH 08/30] Add wallet factory tests --- test/test.WalletFactory.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index c9f8bde5c..7becea6ed 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -94,6 +94,29 @@ describe('WalletFactory model', function() { JSON.stringify(w.toObj()).should.equal(o); }); + it('should create wallet from encrypted object', function() { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage._setPassphrase = sinon.spy(); + wf.storage.import = sinon.spy(); + + var w = wf.fromEncryptedObj("encrypted object", "password"); + should.exist(w); + wf.storage._setPassphrase.called.should.be.true; + wf.storage.import.called.should.be.true; + }); + + it('should import and update indexes', function() { + var wf = new WalletFactory(config, '0.0.1'); + var wallet = {id: "fake wallet", updateIndexes: function(cb) { cb(); }}; + wf.fromEncryptedObj = sinon.stub().returns(wallet); + var callback = sinon.spy(); + + var w = wf.import("encrypted", "password", callback); + + should.exist(w); + wallet.should.equal(w); + sinon.assert.callCount(callback, 1); + }); it('BIP32 length problem', function() { var sconfig = { From 1639b796cf527d9cbd7d63b52dd8f05fb0bc3197 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 25 Jun 2014 17:14:12 -0300 Subject: [PATCH 09/30] intermediate screen backup --- index.html | 46 +++++++++++++++++++++++---------- js/controllers/header.js | 9 ++++++- js/controllers/setup.js | 3 +-- js/controllers/signin.js | 3 +-- js/models/core/Wallet.js | 16 +++++++++++- js/models/core/WalletFactory.js | 1 + 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/index.html b/index.html index e7825c84c..b6ec101e8 100644 --- a/index.html +++ b/index.html @@ -20,7 +20,7 @@
-
-
+
-
+
Not all copayers have joined your wallet yet. @@ -114,10 +114,14 @@ yet to join.
+
+ + All copayers have joined the wallet, it's ready for use! +
-
+

Share this secret with your other copayers @@ -141,7 +145,18 @@
- Copayer {{$index+1}}-{{totalCopayers}} + + + +
@@ -152,12 +167,12 @@
-
+
-