From 45d44a927b3a5ec99d87223c3922771a3e9f9cd7 Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 27 Jun 2016 16:01:06 -0300 Subject: [PATCH 01/10] fix wallet lock - add tabs in export wallet --- public/views/export.html | 139 +++++++++++++++++++---------------- src/js/controllers/backup.js | 8 +- src/js/controllers/export.js | 89 +++++++++++++++++----- 3 files changed, 148 insertions(+), 88 deletions(-) diff --git a/public/views/export.html b/public/views/export.html index 7aa69fae8..32dbaa08b 100644 --- a/public/views/export.html +++ b/public/views/export.html @@ -5,89 +5,99 @@
-

-
-
- - Failed to export +
+
+ +
+ QR Code +
+
+
+
+
+ + Failed to export +
+ +
-
- - A spending password is set for this wallet. Exporting keeps the spending password in the export archive. + +
+ +
+ + +
+
+ -
-
-
- -
- -
+

- -
- -
-
-
-
+ + Do not include private key + -

- - - Do not include private key - - -
- - - - WARNING: The private key of this wallet is not available. The export allows to check the wallet balance, transaction history, and create spend proposals from the export. However, does not allow to approve (sign) proposals, so funds will not be accessible from the export. - +
+ + + + WARNING: The private key of this wallet is not available. The export allows to check the wallet balance, transaction history, and create spend proposals from the export. However, does not allow to approve (sign) proposals, so funds will not be accessible from the export. -
+
+
- -
- - - - WARNING: Not including the private key allows to check the wallet balance, transaction history, and create spend proposals from the export. However, does not allow to approve (sign) proposals, so funds will not be accessible from the export. - +
+ + + + WARNING: Not including the private key allows to check the wallet balance, transaction history, and create spend proposals from the export. However, does not allow to approve (sign) proposals, so funds will not be accessible from the export. -
+
+
-
-
- + +
+

Export options

+ - + -
-

Export options

- - -
+ ng-click="sendWalletBackup()"> + Send by email
+
+
+
+ +
@@ -102,6 +112,5 @@
-
diff --git a/src/js/controllers/backup.js b/src/js/controllers/backup.js index 320144800..84008adf4 100644 --- a/src/js/controllers/backup.js +++ b/src/js/controllers/backup.js @@ -23,8 +23,7 @@ angular.module('copayApp.controllers').controller('backupController', handleEncryptedWallet(fc, function(err) { if (err) { - $scope.error = bwsError.msg(err, gettext('Could not decrypt')); - $log.warn('Error decrypting credentials:', $scope.error); + go.path(prevState); return; } $scope.credentialsEncrypted = false; @@ -69,10 +68,13 @@ angular.module('copayApp.controllers').controller('backupController', }; $scope.goBack = function() { - walletService.lock(fc); go.path(prevState || 'walletHome'); }; + $scope.$on('$destroy', function() { + walletService.lock(fc); + }); + $scope.goToStep = function(n) { if (n == 1) $scope.initFlow(); diff --git a/src/js/controllers/export.js b/src/js/controllers/export.js index cea7af04a..cb7561458 100644 --- a/src/js/controllers/export.js +++ b/src/js/controllers/export.js @@ -1,39 +1,88 @@ 'use strict'; angular.module('copayApp.controllers').controller('exportController', - function($scope, $timeout, $log, backupService, fingerprintService, configService, storageService, profileService, platformInfo, notification, go, gettext, gettextCatalog) { + function($rootScope, $scope, $timeout, $log, lodash, backupService, walletService, fingerprintService, configService, storageService, profileService, platformInfo, notification, go, gettext, gettextCatalog) { + var prevState; var isWP = platformInfo.isWP; var isAndroid = platformInfo.isAndroid; - var isCordova = platformInfo.isCordova; - - $scope.error = null; - $scope.success = null; var fc = profileService.focusedClient; $scope.isEncrypted = fc.isPrivKeyEncrypted(); - $scope.touchidSuccess = null; - $scope.touchidEnabled = null; + $scope.isCordova = platformInfo.isCordova; + $scope.isSafari = platformInfo.isSafari; $scope.error = null; $scope.init = function(state) { - if (!isCordova) return; - - var config = configService.getSync(); - var touchidAvailable = fingerprintService.isAvailable(); - var touchidEnabled = $scope.touchidEnabled = config.touchIdFor ? config.touchIdFor[fc.credentials.walletId] : null; - - if (!touchidAvailable || !touchidEnabled) return; + $scope.QROpts = false; + prevState = state || 'walletHome'; fingerprintService.check(fc, function(err) { - if (err) - go.path(state || 'walletHome'); + if (err) { + go.path(prevState); + return; + } - $scope.touchidSuccess = true; - $timeout(function() { - $scope.$apply(); - }, 10); + handleEncryptedWallet(fc, function(err) { + if (err) { + go.path(prevState); + return; + } + + $scope.exportWalletInfo = encodeWalletInfo(); + $timeout(function() { + $scope.$apply(); + }, 1); + }); }); }; + $scope.$on('$destroy', function() { + walletService.lock(fc); + }); + + function handleEncryptedWallet(client, cb) { + if (!walletService.isEncrypted(client)) { + $scope.credentialsEncrypted = false; + return cb(); + } + + $rootScope.$emit('Local/NeedsPassword', false, function(err, password) { + if (err) return cb(err); + return cb(walletService.unlock(client, password)); + }); + }; + + function encodeWalletInfo() { + var c = fc.credentials; + var encodingType = { + mnemonic: 1, + xpriv: 2, + xpub: 3 + }; + var info; + + if (c.canSign()) { + if (c.mnemonic) { + info = { + type: encodingType.mnemonic, + data: c.mnemonic + } + } else { + info = { + type: encodingType.xpriv, + data: c.xPrivKey + } + } + } else { + info = { + type: encodingType.xpub, + data: c.xPubKey + } + } + + var code = info.type + c.network.charAt(0).toLowerCase() + info.data; + return code; + }; + $scope.downloadWalletBackup = function() { $scope.getAddressbook(function(err, localAddressBook) { if (err) { From 6aa075326ec26734eecceb927aa94881c37705dd Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 28 Jun 2016 15:34:10 -0300 Subject: [PATCH 02/10] process code - parse information to import wallet --- cordova/build.sh | 3 - public/views/export.html | 2 +- public/views/import.html | 202 +++++++++++++++++------------------ src/js/controllers/export.js | 6 +- src/js/controllers/import.js | 39 ++++++- 5 files changed, 138 insertions(+), 114 deletions(-) diff --git a/cordova/build.sh b/cordova/build.sh index 6a99d667b..c0fb9ed30 100755 --- a/cordova/build.sh +++ b/cordova/build.sh @@ -155,9 +155,6 @@ if [ ! -d $PROJECT ]; then cordova plugin add cordova-plugin-disable-bitcode checkOK - cordova plugin add cordova-plugin-android-fingerprint-auth - checkOK - cordova plugin add cordova-plugin-screen-orientation checkOK diff --git a/public/views/export.html b/public/views/export.html index 32dbaa08b..26fa7e069 100644 --- a/public/views/export.html +++ b/public/views/export.html @@ -96,7 +96,7 @@
- +
diff --git a/public/views/import.html b/public/views/import.html index 5ce29400c..c79c0086b 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -24,83 +24,76 @@
-
-
Could not access the wallet at the server. Please check:
-
    -
  • The password of the recovery phrase (if set) -
  • -
  • The derivation path -
  • -
  • The wallet service URL -
-
- NOTE: To import a wallet from a 3rd party software, please go to Add Wallet > Create Wallet, and specify the Recovery Phrase there.
-
+
+
Could not access the wallet at the server. Please check:
+
    +
  • The password of the recovery phrase (if set)
  • +
  • The derivation path
  • +
  • The wallet service URL +
+
+ NOTE: To import a wallet from a 3rd party software, please go to Add Wallet > Create Wallet, and specify the Recovery Phrase there.
+
-
- {{import.error|translate}} -
+
{{import.error|translate}}
-
+ + +
+ +
+ -
- - -
+ - -
-
- -
@@ -175,58 +168,55 @@
-
-
- No hardware wallets supported on this device -
-
-
- -
- -
- - -
- -
- - Shared Wallet - -
- - -
-
- - -
-
- - - -
+
+ No hardware wallets supported on this device
+
+
+ +
+ +
+ + +
+ +
+ + Shared Wallet + +
+ + +
+
+ + +
+
+ + +
diff --git a/src/js/controllers/export.js b/src/js/controllers/export.js index cb7561458..62244fae3 100644 --- a/src/js/controllers/export.js +++ b/src/js/controllers/export.js @@ -10,6 +10,7 @@ angular.module('copayApp.controllers').controller('exportController', $scope.isCordova = platformInfo.isCordova; $scope.isSafari = platformInfo.isSafari; $scope.error = null; + console.log(fc.credentials); $scope.init = function(state) { $scope.QROpts = false; @@ -64,7 +65,7 @@ angular.module('copayApp.controllers').controller('exportController', if (c.mnemonic) { info = { type: encodingType.mnemonic, - data: c.mnemonic + data: c.mnemonic, } } else { info = { @@ -79,7 +80,8 @@ angular.module('copayApp.controllers').controller('exportController', } } - var code = info.type + c.network.charAt(0).toLowerCase() + info.data; + var code = info.type + '|' + c.network.charAt(0).toLowerCase() + '|' + info.data + '|' + c.account + '|' + c.derivationStrategy + + '|' + (c.mnemonicHasPassphrase || null); return code; }; diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index af5a44cd9..a9afd7d97 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -13,6 +13,7 @@ angular.module('copayApp.controllers').controller('importController', $scope.bwsurl = defaults.bws.url; $scope.derivationPath = derivationPathHelper.default; $scope.account = 1; + $scope.processingCode = null; self.importErr = false; var updateSeedSourceSelect = function() { @@ -34,12 +35,46 @@ angular.module('copayApp.controllers').controller('importController', } }; + $scope.processCode = function(code) { + var parsedCode = code.split('|'); + var derivationStrategy = "44'"; + var networkVal; + + var info = { + type: parsedCode[0], + network: parsedCode[1], + data: parsedCode[2], + account: parsedCode[3], + derivationStrategy: parsedCode[4], + hasPassphrase: parsedCode[5] + }; + + $scope.words = info.data; + + if (info.network == 't') { + networkVal = "1'"; + $scope.testnetEnabled = true; + } else { + networkVal = "0'"; + $scope.testnetEnabled = false; + } + + if (info.derivationStrategy == 'BIP45' || info.derivationStrategy == 'BIP48') + derivationStrategy = info.derivationStrategy.substring(3, 5) + "'"; + + $scope.derivationPath = "m/" + derivationStrategy + '/' + networkVal + '/' + info.account + "'"; + + $timeout(function() { + $rootScope.$apply(); + }, 1); + }; + this.setType = function(type) { $scope.type = type; this.error = null; $timeout(function() { $rootScope.$apply(); - }); + }, 1); }; var _importBlob = function(str, opts) { @@ -130,7 +165,7 @@ angular.module('copayApp.controllers').controller('importController', $scope.derivationPath = derivationPathHelper.defaultTestnet; else $scope.derivationPath = derivationPathHelper.default; - } + }; $scope.getFile = function() { // If we use onloadend, we need to check the readyState. From afc2598d592818eb318f37d88148474975fe2c56 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 28 Jun 2016 17:29:47 -0300 Subject: [PATCH 03/10] refactor - add spinner --- public/views/export.html | 4 +-- public/views/import.html | 2 +- src/js/controllers/export.js | 5 +--- src/js/controllers/import.js | 41 ++++++++++++++++++------------- src/js/services/onGoingProcess.js | 1 + 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/public/views/export.html b/public/views/export.html index 26fa7e069..eec227984 100644 --- a/public/views/export.html +++ b/public/views/export.html @@ -95,8 +95,8 @@ -
- +
+
diff --git a/public/views/import.html b/public/views/import.html index c79c0086b..882b643ae 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -69,7 +69,7 @@ diff --git a/src/js/controllers/export.js b/src/js/controllers/export.js index 62244fae3..395bdcd46 100644 --- a/src/js/controllers/export.js +++ b/src/js/controllers/export.js @@ -10,7 +10,6 @@ angular.module('copayApp.controllers').controller('exportController', $scope.isCordova = platformInfo.isCordova; $scope.isSafari = platformInfo.isSafari; $scope.error = null; - console.log(fc.credentials); $scope.init = function(state) { $scope.QROpts = false; @@ -80,9 +79,7 @@ angular.module('copayApp.controllers').controller('exportController', } } - var code = info.type + '|' + c.network.charAt(0).toLowerCase() + '|' + info.data + '|' + c.account + '|' + c.derivationStrategy + - '|' + (c.mnemonicHasPassphrase || null); - return code; + return info.type + '|' + info.data; }; $scope.downloadWalletBackup = function() { diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index a9afd7d97..4f05bb486 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -36,35 +36,42 @@ angular.module('copayApp.controllers').controller('importController', }; $scope.processCode = function(code) { + ongoingProcess.set('processingCode', true); + self.importErr = false; var parsedCode = code.split('|'); - var derivationStrategy = "44'"; - var networkVal; + + if (parsedCode.length != 2) { + ongoingProcess.set('processingCode', false); + return; + } var info = { type: parsedCode[0], - network: parsedCode[1], - data: parsedCode[2], - account: parsedCode[3], - derivationStrategy: parsedCode[4], - hasPassphrase: parsedCode[5] + data: parsedCode[1], }; - $scope.words = info.data; + var client = bwcService.getClient(null, null); - if (info.network == 't') { - networkVal = "1'"; - $scope.testnetEnabled = true; - } else { - networkVal = "0'"; - $scope.testnetEnabled = false; + if (info.type == 1) { + client.seedFromMnemonic(info.data, {}); + } + if (info.type == 2) { + client.seedFromExtendedPrivateKey(info.data, {}); + } + if (info.type == 3) { + client.seedFromExtendedPublicKey(info.data, {}); } - if (info.derivationStrategy == 'BIP45' || info.derivationStrategy == 'BIP48') - derivationStrategy = info.derivationStrategy.substring(3, 5) + "'"; + $scope.words = info.data; + $scope.derivationPath = client.credentials.getBaseAddressDerivationPath(); - $scope.derivationPath = "m/" + derivationStrategy + '/' + networkVal + '/' + info.account + "'"; + if (client.credentials.network == 'testnet') + $scope.testnetEnabled = true; + else + $scope.testnetEnabled = false; $timeout(function() { + ongoingProcess.set('processingCode', false); $rootScope.$apply(); }, 1); }; diff --git a/src/js/services/onGoingProcess.js b/src/js/services/onGoingProcess.js index 9a9ed7547..fba2093a4 100644 --- a/src/js/services/onGoingProcess.js +++ b/src/js/services/onGoingProcess.js @@ -28,6 +28,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti 'importingWallet': gettext('Importing Wallet...'), 'sweepingWallet': gettext('Sweeping Wallet...'), 'deletingWallet': gettext('Deleting Wallet...'), + 'processingCode': gettext('Processing code...'), }; root.clear = function() { From dbd78a5ad152932d325411708deb14180c56a6d6 Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 29 Jun 2016 10:19:49 -0300 Subject: [PATCH 04/10] complete import process - scope only --- public/views/import.html | 50 +++++++-------- src/js/controllers/export.js | 4 +- src/js/controllers/import.js | 120 ++++++++++++++++++++--------------- 3 files changed, 96 insertions(+), 78 deletions(-) diff --git a/public/views/import.html b/public/views/import.html index 882b643ae..d7bfff77e 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -4,17 +4,17 @@ ng-init="titleSection='Import wallet'; goBackToState = 'add'; noColor = true">
-
+
@@ -23,8 +23,8 @@
-
-
+
+
Could not access the wallet at the server. Please check:
  • The password of the recovery phrase (if set)
  • @@ -37,15 +37,15 @@
-
-
{{import.error|translate}}
+
+
{{error|translate}}
-
+ @@ -101,33 +101,33 @@
-
+
- {{import.error|translate}} + {{error|translate}}
- +
+ name="backupFile" ng-model="backupFile" ng-file-select>
- +
+ name="password" ng-model="password">
@@ -150,7 +150,7 @@
@@ -161,34 +161,34 @@
-
+
- {{import.error|translate}} + {{error|translate}}
-
-
+ +
No hardware wallets supported on this device
-
+
-
+
-
+
Shared Wallet diff --git a/src/js/controllers/export.js b/src/js/controllers/export.js index 395bdcd46..c60eaa3ef 100644 --- a/src/js/controllers/export.js +++ b/src/js/controllers/export.js @@ -10,6 +10,7 @@ angular.module('copayApp.controllers').controller('exportController', $scope.isCordova = platformInfo.isCordova; $scope.isSafari = platformInfo.isSafari; $scope.error = null; + console.log(fc.credentials); $scope.init = function(state) { $scope.QROpts = false; @@ -79,7 +80,8 @@ angular.module('copayApp.controllers').controller('exportController', } } - return info.type + '|' + info.data; + var code = info.type + '|' + info.data + '|' + c.network.charAt(0).toLowerCase() + '|' + c.account + '|' + c.derivationStrategy + '|' + (c.mnemonicHasPassphrase); + return code; }; $scope.downloadWalletBackup = function() { diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 4f05bb486..2a34c7516 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -1,12 +1,10 @@ 'use strict'; angular.module('copayApp.controllers').controller('importController', - function($scope, $rootScope, $timeout, $log, profileService, configService, notification, go, sjcl, gettext, lodash, ledger, trezor, derivationPathHelper, platformInfo, bwsError, bwcService, ongoingProcess) { + function($scope, $rootScope, $timeout, $log, profileService, configService, notification, go, sjcl, gettext, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess) { var isChromeApp = platformInfo.isChromeApp; var isDevel = platformInfo.isDevel; - - var self = this; var reader = new FileReader(); var defaults = configService.getDefaults(); var errors = bwcService.getErrors(); @@ -14,52 +12,70 @@ angular.module('copayApp.controllers').controller('importController', $scope.derivationPath = derivationPathHelper.default; $scope.account = 1; $scope.processingCode = null; - self.importErr = false; + $scope.importErr = false; var updateSeedSourceSelect = function() { - self.seedOptions = []; + $scope.seedOptions = []; if (isChromeApp) { - self.seedOptions.push({ + $scope.seedOptions.push({ id: 'ledger', label: 'Ledger Hardware Wallet', }); } if (isChromeApp || isDevel) { - self.seedOptions.push({ + $scope.seedOptions.push({ id: 'trezor', label: 'Trezor Hardware Wallet', }); - $scope.seedSource = self.seedOptions[0]; + $scope.seedSource = $scope.seedOptions[0]; } }; $scope.processCode = function(code) { + $scope.importErr = false; + $scope.error = null; ongoingProcess.set('processingCode', true); - self.importErr = false; var parsedCode = code.split('|'); - if (parsedCode.length != 2) { + if (parsedCode.length != 6) { ongoingProcess.set('processingCode', false); + $log.debug('Missing parameters'); return; } var info = { type: parsedCode[0], data: parsedCode[1], + network: parsedCode[2] == 't' ? 'testnet' : 'livenet', + account: parseInt(parsedCode[3]), + derivationStrategy: parsedCode[4], + mnemonicHasPassphrase: parsedCode[5] }; var client = bwcService.getClient(null, null); if (info.type == 1) { - client.seedFromMnemonic(info.data, {}); + client.seedFromMnemonic(info.data, { + network: info.network, + account: info.account, + derivationStrategy: info.derivationStrategy + }); } + if (info.type == 2) { - client.seedFromExtendedPrivateKey(info.data, {}); + client.seedFromExtendedPrivateKey(info.data, { + account: info.account, + derivationStrategy: info.derivationStrategy + }); } + if (info.type == 3) { - client.seedFromExtendedPublicKey(info.data, {}); + client.seedFromExtendedPublicKey(info.data, { + account: info.account, + derivationStrategy: info.derivationStrategy + }); } $scope.words = info.data; @@ -76,9 +92,9 @@ angular.module('copayApp.controllers').controller('importController', }, 1); }; - this.setType = function(type) { + $scope.setType = function(type) { $scope.type = type; - this.error = null; + $scope.error = null; $timeout(function() { $rootScope.$apply(); }, 1); @@ -87,14 +103,14 @@ angular.module('copayApp.controllers').controller('importController', var _importBlob = function(str, opts) { var str2, err; try { - str2 = sjcl.decrypt(self.password, str); + str2 = sjcl.decrypt($scope.password, str); } catch (e) { err = gettext('Could not decrypt file, check your password'); $log.warn(e); }; if (err) { - self.error = err; + $scope.error = err; $timeout(function() { $rootScope.$apply(); }); @@ -109,7 +125,7 @@ angular.module('copayApp.controllers').controller('importController', profileService.importWallet(str2, opts, function(err, walletId) { ongoingProcess.set('importingWallet', false); if (err) { - self.error = err; + $scope.error = err; } else { $rootScope.$emit('Local/WalletImported', walletId); notification.success(gettext('Success'), gettext('Your wallet has been imported correctly')); @@ -126,9 +142,9 @@ angular.module('copayApp.controllers').controller('importController', ongoingProcess.set('importingWallet', false); if (err) { if (err instanceof errors.NOT_AUTHORIZED) { - self.importErr = true; + $scope.importErr = true; } else { - self.error = err; + $scope.error = err; } return $timeout(function() { $scope.$apply(); @@ -151,9 +167,9 @@ angular.module('copayApp.controllers').controller('importController', if (err) { if (err instanceof errors.NOT_AUTHORIZED) { - self.importErr = true; + $scope.importErr = true; } else { - self.error = err; + $scope.error = err; } return $timeout(function() { $scope.$apply(); @@ -185,9 +201,9 @@ angular.module('copayApp.controllers').controller('importController', } }; - this.importBlob = function(form) { + $scope.importBlob = function(form) { if (form.$invalid) { - this.error = gettext('There is an error in the form'); + $scope.error = gettext('There is an error in the form'); $timeout(function() { $scope.$apply(); }); @@ -199,7 +215,7 @@ angular.module('copayApp.controllers').controller('importController', var password = form.password.$modelValue; if (!backupFile && !backupText) { - this.error = gettext('Please, select your backup file'); + $scope.error = gettext('Please, select your backup file'); $timeout(function() { $scope.$apply(); }); @@ -216,9 +232,9 @@ angular.module('copayApp.controllers').controller('importController', } }; - this.importMnemonic = function(form) { + $scope.importMnemonic = function(form) { if (form.$invalid) { - this.error = gettext('There is an error in the form'); + $scope.error = gettext('There is an error in the form'); $timeout(function() { $scope.$apply(); }); @@ -232,7 +248,7 @@ angular.module('copayApp.controllers').controller('importController', var pathData = derivationPathHelper.parse($scope.derivationPath); if (!pathData) { - this.error = gettext('Invalid derivation path'); + $scope.error = gettext('Invalid derivation path'); return; } opts.account = pathData.account; @@ -240,21 +256,21 @@ angular.module('copayApp.controllers').controller('importController', opts.derivationStrategy = pathData.derivationStrategy; var words = form.words.$modelValue; - this.error = null; + $scope.error = null; if (!words) { - this.error = gettext('Please enter the recovery phrase'); + $scope.error = gettext('Please enter the recovery phrase'); } else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) { return _importExtendedPrivateKey(words, opts); } else { var wordList = words.split(/[\u3000\s]+/); if ((wordList.length % 3) != 0) { - this.error = gettext('Wrong number of recovery words:') + wordList.length; + $scope.error = gettext('Wrong number of recovery words:') + wordList.length; } } - if (this.error) { + if ($scope.error) { $timeout(function() { $scope.$apply(); }); @@ -267,12 +283,12 @@ angular.module('copayApp.controllers').controller('importController', _importMnemonic(words, opts); }; - this.importTrezor = function(account, isMultisig) { - var self = this; + $scope.importTrezor = function(account, isMultisig) { + var $scope = $scope; trezor.getInfoForNewWallet(isMultisig, account, function(err, lopts) { ongoingProcess.clear(); if (err) { - self.error = err; + $scope.error = err; $scope.$apply(); return; } @@ -285,7 +301,7 @@ angular.module('copayApp.controllers').controller('importController', profileService.importExtendedPublicKey(lopts, function(err, walletId) { ongoingProcess.set('importingWallet', false); if (err) { - self.error = err; + $scope.error = err; return $timeout(function() { $scope.$apply(); }); @@ -297,56 +313,56 @@ angular.module('copayApp.controllers').controller('importController', }, 100); }; - this.importHW = function(form) { + $scope.importHW = function(form) { if (form.$invalid || $scope.account < 0) { - this.error = gettext('There is an error in the form'); + $scope.error = gettext('There is an error in the form'); $timeout(function() { $scope.$apply(); }); return; } - this.error = ''; - this.importErr = false; + $scope.error = ''; + $scope.importErr = false; var account = +$scope.account; - if (self.seedSourceId == 'trezor') { + if ($scope.seedSourceId == 'trezor') { if (account < 1) { - this.error = gettext('Invalid account number'); + $scope.error = gettext('Invalid account number'); return; } account = account - 1; } - switch (self.seedSourceId) { + switch ($scope.seedSourceId) { case ('ledger'): ongoingProcess.set('connectingledger', true); - self.importLedger(account); + $scope.importLedger(account); break; case ('trezor'): ongoingProcess.set('connectingtrezor', true); - self.importTrezor(account, $scope.isMultisig); + $scope.importTrezor(account, $scope.isMultisig); break; default: throw ('Error: bad source id'); }; }; - this.setSeedSource = function() { + $scope.setSeedSource = function() { if (!$scope.seedSource) return; - self.seedSourceId = $scope.seedSource.id; + $scope.seedSourceId = $scope.seedSource.id; $timeout(function() { $rootScope.$apply(); }); }; - this.importLedger = function(account) { - var self = this; + $scope.importLedger = function(account) { + var $scope = $scope; ledger.getInfoForNewWallet(true, account, function(err, lopts) { ongoingProcess.clear(); if (err) { - self.error = err; + $scope.error = err; $scope.$apply(); return; } @@ -359,7 +375,7 @@ angular.module('copayApp.controllers').controller('importController', profileService.importExtendedPublicKey(lopts, function(err, walletId) { ongoingProcess.set('importingWallet', false); if (err) { - self.error = err; + $scope.error = err; return $timeout(function() { $scope.$apply(); }); @@ -372,5 +388,5 @@ angular.module('copayApp.controllers').controller('importController', }; updateSeedSourceSelect(); - self.setSeedSource('new'); + $scope.setSeedSource('new'); }); From 51bee061b10210e266e1255cdfef1de82c30b43f Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 29 Jun 2016 12:24:31 -0300 Subject: [PATCH 05/10] improve error msg - warning if has passphrase - hide QR data scanned (lock icon) --- public/views/import.html | 9 +++++++-- src/js/controllers/export.js | 1 - src/js/controllers/import.js | 17 ++++++++++++----- src/sass/main.scss | 8 ++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/public/views/import.html b/public/views/import.html index d7bfff77e..32ab29bf9 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -46,13 +46,18 @@
-
-
+
Failed to export
- +
@@ -44,11 +44,35 @@
-

+
+
+ +
- - Do not include private key - +
+ Exporting Walelt: + {{index.walletName}} +
+
From/In the destination device, go to Add wallet > Import wallet and scan this QR code
+
+ +
+ +
+ + Do not include private key + +
@@ -68,7 +92,7 @@
-
+
-
- - -
-

Wallet Export

diff --git a/src/js/controllers/export.js b/src/js/controllers/export.js index 423c11d22..d076759c7 100644 --- a/src/js/controllers/export.js +++ b/src/js/controllers/export.js @@ -12,7 +12,8 @@ angular.module('copayApp.controllers').controller('exportController', $scope.error = null; $scope.init = function(state) { - $scope.QROpts = false; + $scope.noSignEnabled = false; + $scope.showAdvanced = false; prevState = state || 'walletHome'; fingerprintService.check(fc, function(err) { @@ -35,6 +36,13 @@ angular.module('copayApp.controllers').controller('exportController', }); }; + $scope.noSignEnabledChange = function() { + $scope.exportWalletInfo = encodeWalletInfo(); + $timeout(function() { + $scope.$apply(); + }, 1); + }; + $scope.$on('$destroy', function() { walletService.lock(fc); }); @@ -60,7 +68,7 @@ angular.module('copayApp.controllers').controller('exportController', }; var info; - if (c.canSign()) { + if (c.canSign() && !$scope.noSignEnabled) { if (c.mnemonic) { info = { type: encodingType.mnemonic, From 84b92044a238619b854a484bfc1be455971d5ed8 Mon Sep 17 00:00:00 2001 From: Javier Date: Wed, 29 Jun 2016 17:04:40 -0300 Subject: [PATCH 07/10] refactor --- public/views/export.html | 24 +++++------ public/views/import.html | 4 +- src/js/controllers/backup.js | 1 + src/js/controllers/export.js | 14 +++++- src/js/controllers/import.js | 71 ++++++++++++++----------------- src/js/services/onGoingProcess.js | 2 +- src/sass/main.scss | 4 ++ 7 files changed, 62 insertions(+), 58 deletions(-) diff --git a/public/views/export.html b/public/views/export.html index ecb4e507c..e26266d35 100644 --- a/public/views/export.html +++ b/public/views/export.html @@ -5,15 +5,16 @@
-
+

+
- -
@@ -45,18 +46,13 @@
-
+
- -
- Exporting Walelt: - {{index.walletName}} -
-
From/In the destination device, go to Add wallet > Import wallet and scan this QR code
+
From the destination device, go to Add wallet > Import wallet and scan this QR code
-
+
-
+
- WARNING: The private key of this wallet is not available. The export allows to check the wallet balance, transaction history, and create spend proposals from the export. However, does not allow to approve (sign) proposals, so funds will not be accessible from the export. + WARNING: The private key of this wallet is not available. The export allows to check the wallet balance, transaction history, and create spend proposals from the export. However, does not allow to approve (sign) proposals, so funds will not be accessible from the export.
-
+
diff --git a/public/views/import.html b/public/views/import.html index 32ab29bf9..5b28a0edc 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -29,7 +29,7 @@
  • The password of the recovery phrase (if set)
  • The derivation path
  • -
  • The wallet service URL +
  • The wallet service URL
NOTE: To import a wallet from a 3rd party software, please go to Add Wallet > Create Wallet, and specify the Recovery Phrase there.
@@ -51,7 +51,7 @@
- +
diff --git a/src/js/controllers/backup.js b/src/js/controllers/backup.js index 84008adf4..7cbeaf093 100644 --- a/src/js/controllers/backup.js +++ b/src/js/controllers/backup.js @@ -23,6 +23,7 @@ angular.module('copayApp.controllers').controller('backupController', handleEncryptedWallet(fc, function(err) { if (err) { + $log.warn('Error decrypting credentials:', $scope.error); go.path(prevState); return; } diff --git a/src/js/controllers/export.js b/src/js/controllers/export.js index d076759c7..713066340 100644 --- a/src/js/controllers/export.js +++ b/src/js/controllers/export.js @@ -12,6 +12,7 @@ angular.module('copayApp.controllers').controller('exportController', $scope.error = null; $scope.init = function(state) { + $scope.exportQR = false; $scope.noSignEnabled = false; $scope.showAdvanced = false; prevState = state || 'walletHome'; @@ -36,12 +37,16 @@ angular.module('copayApp.controllers').controller('exportController', }); }; + /* + EXPORT WITHOUT PRIVATE KEY - PENDING + $scope.noSignEnabledChange = function() { $scope.exportWalletInfo = encodeWalletInfo(); $timeout(function() { $scope.$apply(); }, 1); }; + */ $scope.$on('$destroy', function() { walletService.lock(fc); @@ -61,6 +66,7 @@ angular.module('copayApp.controllers').controller('exportController', function encodeWalletInfo() { var c = fc.credentials; + var derivationPath = fc.credentials.getBaseAddressDerivationPath(); var encodingType = { mnemonic: 1, xpriv: 2, @@ -81,13 +87,19 @@ angular.module('copayApp.controllers').controller('exportController', } } } else { + /* + EXPORT WITHOUT PRIVATE KEY - PENDING + info = { type: encodingType.xpub, data: c.xPubKey } + */ + + return null; } - var code = info.type + '|' + info.data + '|' + c.network.charAt(0).toLowerCase() + '|' + c.account + '|' + c.derivationStrategy + '|' + (c.mnemonicHasPassphrase); + var code = info.type + '|' + info.data + '|' + c.network.toLowerCase() + '|' + derivationPath + '|' + (c.mnemonicHasPassphrase); return code; }; diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 496e451ed..59a80e138 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -12,7 +12,6 @@ angular.module('copayApp.controllers').controller('importController', $scope.bwsurl = defaults.bws.url; $scope.derivationPath = derivationPathHelper.default; $scope.account = 1; - $scope.processingCode = null; $scope.importErr = false; $scope.fromQR = null; @@ -35,15 +34,13 @@ angular.module('copayApp.controllers').controller('importController', } }; - $scope.processCode = function(code) { + $scope.processWalletInfo = function(code) { $scope.fromQR = null; $scope.importErr = false; $scope.error = null; - ongoingProcess.set('processingCode', true); var parsedCode = code.split('|'); - if (parsedCode.length != 6) { - ongoingProcess.set('processingCode', false); + if (parsedCode.length != 5) { $scope.error = gettext('Cannot read the code properly. Missing parameters'); return; } @@ -51,48 +48,18 @@ angular.module('copayApp.controllers').controller('importController', var info = { type: parsedCode[0], data: parsedCode[1], - network: parsedCode[2] == 't' ? 'testnet' : 'livenet', - account: parseInt(parsedCode[3]), - derivationStrategy: parsedCode[4], - hasPassphrase: parsedCode[5] == 'true' ? true : false + network: parsedCode[2], + derivationPath: parsedCode[3], + hasPassphrase: parsedCode[4] == 'true' ? true : false }; if (info.type == 1 && info.hasPassphrase) $scope.error = gettext('Password required. Make sure to enter your password in advanced options'); - var client = bwcService.getClient(null, null); - - if (info.type == 1) { - client.seedFromMnemonic(info.data, { - network: info.network, - account: info.account, - derivationStrategy: info.derivationStrategy - }); - } - - if (info.type == 2) { - client.seedFromExtendedPrivateKey(info.data, { - account: info.account, - derivationStrategy: info.derivationStrategy - }); - } - - if (info.type == 3) { - client.seedFromExtendedPublicKey(info.data, { - account: info.account, - derivationStrategy: info.derivationStrategy - }); - } - - $scope.derivationPath = client.credentials.getBaseAddressDerivationPath(); - - if (client.credentials.network == 'testnet') - $scope.testnetEnabled = true; - else - $scope.testnetEnabled = false; + $scope.derivationPath = info.derivationPath; + $scope.testnetEnabled = info.network == 'testnet' ? true : false; $timeout(function() { - ongoingProcess.set('processingCode', false); $scope.fromQR = true; $scope.words = null; dataFromQR = info.data; @@ -166,6 +133,28 @@ angular.module('copayApp.controllers').controller('importController', }, 100); }; + /* + IMPORT FROM PUBLIC KEY - PENDING + + var _importExtendedPublicKey = function(xPubKey, opts) { + ongoingProcess.set('importingWallet', true); + $timeout(function() { + profileService.importExtendedPublicKey(opts, function(err, walletId) { + ongoingProcess.set('importingWallet', false); + if (err) { + $scope.error = err; + return $timeout(function() { + $scope.$apply(); + }); + } + $rootScope.$emit('Local/WalletImported', walletId); + notification.success(gettext('Success'), gettext('Your wallet has been imported correctly')); + go.walletHome(); + }); + }, 100); + }; + */ + var _importMnemonic = function(words, opts) { ongoingProcess.set('importingWallet', true); @@ -269,6 +258,8 @@ angular.module('copayApp.controllers').controller('importController', $scope.error = gettext('Please enter the recovery phrase'); } else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) { return _importExtendedPrivateKey(words, opts); + } else if (words.indexOf('xpub') == 0 || words.indexOf('tpuv') == 0) { + return _importExtendedPublicKey(words, opts); } else { var wordList = words.split(/[\u3000\s]+/); diff --git a/src/js/services/onGoingProcess.js b/src/js/services/onGoingProcess.js index fba2093a4..836061f5f 100644 --- a/src/js/services/onGoingProcess.js +++ b/src/js/services/onGoingProcess.js @@ -28,7 +28,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti 'importingWallet': gettext('Importing Wallet...'), 'sweepingWallet': gettext('Sweeping Wallet...'), 'deletingWallet': gettext('Deleting Wallet...'), - 'processingCode': gettext('Processing code...'), + 'extractingWalletInfo': gettext('Extracting Wallet Information...'), }; root.clear = function() { diff --git a/src/sass/main.scss b/src/sass/main.scss index 7a96f9050..aeb6bd3e2 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -699,6 +699,10 @@ ul.manage li { padding-left: 25px; } +.p15l { + padding-left: 15px; +} + .p15 { padding: 15px; } From d7a2eeafa8e42813df0918c07179709ce66cdd50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Thu, 30 Jun 2016 10:46:51 -0300 Subject: [PATCH 08/10] lock text area --- public/views/import.html | 13 +++++++++---- src/sass/main.scss | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/public/views/import.html b/public/views/import.html index 5b28a0edc..dfbc3cb34 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -50,14 +50,19 @@ Type the Recovery Phrase (usually 12 words): -
+
-
- +
+
+ +
+
+ +
- +
diff --git a/src/sass/main.scss b/src/sass/main.scss index aeb6bd3e2..daaeeb4b8 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -29,6 +29,16 @@ body { right: 0; } +.qr-scanner-input-import { + position: absolute; + top: -5px; + right: 0; +} + +.icon-close-import { + padding: 0px 40px 5px 10px; +} + h1, h2, h3, h4, h5, h6 { color: #2C3E50; } @@ -606,6 +616,10 @@ ul.manage li { margin-right: 10px; } +.m40r { + margin-right: 40px; +} + .m25r { margin-right: 25px; } @@ -878,7 +892,9 @@ ul.manage li { } .lock-fromQR { - margin: 15px 0px -40px 5px; + position: absolute; + width: 100%; + margin-top: 20px; } .tx-proposal i { From 132a5a3efb070d7c5499a9dd73cf2c5a033843eb Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 30 Jun 2016 15:46:02 -0300 Subject: [PATCH 09/10] clear scope scanned data --- public/views/import.html | 10 +++++----- src/js/controllers/import.js | 10 ++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/public/views/import.html b/public/views/import.html index dfbc3cb34..7a72834e8 100644 --- a/public/views/import.html +++ b/public/views/import.html @@ -50,19 +50,19 @@ Type the Recovery Phrase (usually 12 words): -
+
-
-
+
+
-
+
- +
diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 59a80e138..a7d147c3e 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -8,12 +8,11 @@ angular.module('copayApp.controllers').controller('importController', var reader = new FileReader(); var defaults = configService.getDefaults(); var errors = bwcService.getErrors(); - var dataFromQR = null; + $scope.dataFromQR = null; $scope.bwsurl = defaults.bws.url; $scope.derivationPath = derivationPathHelper.default; $scope.account = 1; $scope.importErr = false; - $scope.fromQR = null; var updateSeedSourceSelect = function() { $scope.seedOptions = []; @@ -35,7 +34,7 @@ angular.module('copayApp.controllers').controller('importController', }; $scope.processWalletInfo = function(code) { - $scope.fromQR = null; + $scope.dataFromQR = null; $scope.importErr = false; $scope.error = null; var parsedCode = code.split('|'); @@ -60,9 +59,8 @@ angular.module('copayApp.controllers').controller('importController', $scope.testnetEnabled = info.network == 'testnet' ? true : false; $timeout(function() { - $scope.fromQR = true; $scope.words = null; - dataFromQR = info.data; + $scope.dataFromQR = info.data; $rootScope.$apply(); }, 1); }; @@ -251,7 +249,7 @@ angular.module('copayApp.controllers').controller('importController', opts.networkName = pathData.networkName; opts.derivationStrategy = pathData.derivationStrategy; - var words = form.words.$modelValue || dataFromQR; + var words = form.words.$modelValue || $scope.dataFromQR; $scope.error = null; if (!words) { From 1e5ecf070c3c9b08490975b8e48b7d8f7da7b4cf Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 30 Jun 2016 15:59:57 -0300 Subject: [PATCH 10/10] not supported message --- public/views/export.html | 6 +++++- src/js/controllers/export.js | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/public/views/export.html b/public/views/export.html index e26266d35..6a1b61e2f 100644 --- a/public/views/export.html +++ b/public/views/export.html @@ -45,13 +45,17 @@
-