From 0c69dfb06184cfb61c82d9f08868c057212facfe Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Mon, 5 Dec 2016 17:33:46 -0500 Subject: [PATCH 01/12] Initial Intel TEE integration. --- app-template/package-template.json | 2 +- src/js/controllers/create.js | 39 ++-- src/js/controllers/import.js | 20 +- src/js/controllers/join.js | 14 +- src/js/controllers/preferences.js | 3 - src/js/controllers/preferencesExternal.js | 24 +++ src/js/controllers/preferencesInformation.js | 8 + src/js/controllers/tab-receive.js | 16 ++ src/js/routes.js | 9 + src/js/services/hwWallet.js | 51 +++-- src/js/services/intelTEE.js | 191 +++++++++++++++++++ src/js/services/ledger.js | 36 ++-- src/js/services/platformInfo.js | 1 + src/js/services/profileService.js | 1 + src/js/services/trezor.js | 24 ++- src/js/services/walletService.js | 48 ++++- www/img/icon-inteltee-white.svg | 28 +++ www/views/includes/walletInfo.html | 8 +- www/views/preferences.html | 6 - www/views/preferencesExternal.html | 14 ++ www/views/preferencesInformation.html | 7 + www/views/tab-create-shared.html | 2 +- www/views/tab-import-hardware.html | 2 +- www/views/tab-receive.html | 13 ++ 24 files changed, 492 insertions(+), 75 deletions(-) create mode 100644 src/js/controllers/preferencesExternal.js create mode 100644 src/js/services/intelTEE.js create mode 100644 www/img/icon-inteltee-white.svg create mode 100644 www/views/preferencesExternal.html diff --git a/app-template/package-template.json b/app-template/package-template.json index c6b567f25..054526a24 100644 --- a/app-template/package-template.json +++ b/app-template/package-template.json @@ -56,7 +56,7 @@ "bezier-easing": "^2.0.3", "bhttp": "^1.2.1", "bitauth": "https://github.com/gabrielbazan7/bitauth.git#copay", - "bitcore-wallet-client": "5.1.2", + "bitcore-wallet-client": "git://github.com/isocolsky/bitcore-wallet-client#369eaede49cd64836015fb9b8a502092ee84dc7c", "bower": "^1.7.9", "cordova-android": "5.1.1", "cordova-custom-config": "^3.0.5", diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index 78561a45a..6316fd4f8 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('createController', - function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService) { + function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService) { var isChromeApp = platformInfo.isChromeApp; var isCordova = platformInfo.isCordova; @@ -68,6 +68,9 @@ angular.module('copayApp.controllers').controller('createController', id: 'new', label: gettextCatalog.getString('Random'), }, { + id: walletService.externalSource.intelTEE.id, + label: gettextCatalog(walletService.externalSource.intelTEE.name), + }, { id: 'set', label: gettextCatalog.getString('Specify Recovery Phrase...'), }]; @@ -81,16 +84,16 @@ angular.module('copayApp.controllers').controller('createController', */ if (appConfigService.name == 'copay') { - if (n > 1 && isChromeApp) { + if (n > 1 && isChromeApp) seedOptions.push({ - id: 'ledger', - label: 'Ledger Hardware Wallet', + id: walletService.externalSource.ledger.id, + label: walletService.externalSource.ledger.longName, }); - } + if (isChromeApp || isDevel) { seedOptions.push({ - id: 'trezor', - label: 'Trezor Hardware Wallet', + id: walletService.externalSource.trezor.id, + label: walletService.externalSource.trezor.longName, }); } } @@ -151,22 +154,36 @@ angular.module('copayApp.controllers').controller('createController', return; } - if ($scope.seedSource.id == 'ledger' || $scope.seedSource.id == 'trezor') { + if ($scope.seedSource.id == walletService.externalSource.ledger.id || $scope.seedSource.id == walletService.externalSource.trezor.id || self.seedSourceId == walletService.externalSource.intelTEE.id) { var account = $scope.formData.account; if (!account || account < 1) { popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); return; } - if ($scope.seedSource.id == 'trezor') + if ($scope.seedSource.id == walletService.externalSource.trezor.id || self.seedSource.id == walletService.externalSource.intelTEE.id) account = account - 1; opts.account = account; ongoingProcess.set('connecting' + $scope.seedSource.id, true); - var src = $scope.seedSource.id == 'ledger' ? ledger : trezor; + var src; + switch (self.seedSourceId) { + case walletService.externalSource.ledger.id: + src = legder; + break; + case walletService.externalSource.trezor.id: + src = trezor; + break; + case walletService.externalSource.intelTEE.id: + src = intelTEE; + break; + default: + this.error = gettextCatalog('Invalid seed source id: ' + self.seedSourceId); + return; + } - src.getInfoForNewWallet(opts.n > 1, account, function(err, lopts) { + src.getInfoForNewWallet(opts, function(err, lopts) { ongoingProcess.set('connecting' + $scope.seedSource.id, false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 3b1c96771..4964058ef 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -3,6 +3,8 @@ angular.module('copayApp.controllers').controller('importController', function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, profileService, configService, sjcl, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess, walletService, popupService, gettextCatalog, appConfigService) { + var isChromeApp = platformInfo.isChromeApp; + var isDevel = platformInfo.isDevel; var reader = new FileReader(); var defaults = configService.getDefaults(); var errors = bwcService.getErrors(); @@ -25,15 +27,15 @@ angular.module('copayApp.controllers').controller('importController', if ($scope.isChromeApp) { $scope.seedOptions.push({ - id: 'ledger', - label: 'Ledger Hardware Wallet', + id: walletService.externalSource.ledger.id, + label: walletService.externalSource.ledger.longName, }); } if ($scope.isChromeApp || $scope.isDevel) { $scope.seedOptions.push({ - id: 'trezor', - label: 'Trezor Hardware Wallet', + id: walletService.externalSource.trezor.id, + label: walletService.externalSource.ledger.longName, }); $scope.formData.seedSource = $scope.seedOptions[0]; } @@ -267,7 +269,7 @@ angular.module('copayApp.controllers').controller('importController', return; } - lopts.externalSource = 'trezor'; + lopts.externalSource = walletService.externalSource.trezor.id; lopts.bwsurl = $scope.formData.bwsurl; ongoingProcess.set('importingWallet', true); $log.debug('Import opts', lopts); @@ -293,7 +295,7 @@ angular.module('copayApp.controllers').controller('importController', var account = $scope.formData.account; - if ($scope.formData.seedSource.id == 'trezor') { + if ($scope.formData.seedSource.id == walletService.externalSource.trezor.id) { if (account < 1) { popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); return; @@ -302,11 +304,11 @@ angular.module('copayApp.controllers').controller('importController', } switch ($scope.formData.seedSource.id) { - case ('ledger'): + case (walletService.externalSource.ledger.id): ongoingProcess.set('connectingledger', true); $scope.importLedger(account); break; - case ('trezor'): + case (walletService.externalSource.trezor.id): ongoingProcess.set('connectingtrezor', true); $scope.importTrezor(account, $scope.formData.isMultisig); break; @@ -323,7 +325,7 @@ angular.module('copayApp.controllers').controller('importController', return; } - lopts.externalSource = 'ledger'; + lopts.externalSource = lopts.externalSource = walletService.externalSource.ledger.id; lopts.bwsurl = $scope.formData.bwsurl; ongoingProcess.set('importingWallet', true); $log.debug('Import opts', lopts); diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index 74abe3228..3bbf4813b 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -66,15 +66,15 @@ angular.module('copayApp.controllers').controller('joinController', if (appConfigService.name == 'copay') { if (isChromeApp) { self.seedOptions.push({ - id: 'ledger', - label: 'Ledger Hardware Wallet', + id: walletService.externalSource.ledger.id, + label: walletService.externalSource.ledger.longName, }); } if (isChromeApp || isDevel) { self.seedOptions.push({ - id: 'trezor', - label: 'Trezor Hardware Wallet', + id: walletService.externalSource.trezor.id, + label: walletService.externalSource.trezor.longName, }); } } @@ -130,19 +130,19 @@ angular.module('copayApp.controllers').controller('joinController', return; } - if (self.seedSourceId == 'ledger' || self.seedSourceId == 'trezor') { + if (self.seedSourceId == walletService.externalSource.ledger.id || self.seedSourceId == walletService.externalSource.trezor.id) { var account = $scope.account; if (!account || account < 1) { popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); return; } - if (self.seedSourceId == 'trezor') + if (self.seedSourceId == walletService.externalSource.trezor.id) account = account - 1; opts.account = account; ongoingProcess.set('connecting' + self.seedSourceId, true); - var src = self.seedSourceId == 'ledger' ? ledger : trezor; + var src = self.seedSourceId == walletService.externalSource.ledger.id ? ledger : trezor; src.getInfoForNewWallet(true, account, function(err, lopts) { ongoingProcess.set('connecting' + self.seedSourceId, false); diff --git a/src/js/controllers/preferences.js b/src/js/controllers/preferences.js index 8b1a8dde0..90ff53f29 100644 --- a/src/js/controllers/preferences.js +++ b/src/js/controllers/preferences.js @@ -89,9 +89,6 @@ angular.module('copayApp.controllers').controller('preferencesController', value: $scope.wallet.balanceHidden }; - if (wallet.isPrivKeyExternal) - $scope.externalSource = wallet.getPrivKeyExternalSourceName() == 'ledger' ? 'Ledger' : 'Trezor'; - $scope.touchIdAvailable = fingerprintService.isAvailable(); $scope.touchIdEnabled = { value: config.touchIdFor ? config.touchIdFor[walletId] : null diff --git a/src/js/controllers/preferencesExternal.js b/src/js/controllers/preferencesExternal.js new file mode 100644 index 000000000..9be05b92f --- /dev/null +++ b/src/js/controllers/preferencesExternal.js @@ -0,0 +1,24 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('preferencesExternalController', function($scope, lodash, profileService, walletService) { + var wallet = profileService.getWallet($stateParams.walletId); + + $scope.externalSource = lodash.find(walletService.externalSource, function(source) { + return source.id == wallet.getPrivKeyExternalSourceName(); + }).name; + + $scope.showMneumonicFromHardwarePopup = function() { + var title = gettextCatalog.getString('Warning!'); + var message = gettextCatalog.getString('Are you being watched? Anyone with your recovery phrase can access or spend your bitcoin.'); + popupService.showConfirm(title, message, null, null, function(res) { + if (res) { + walletService.showMneumonicFromHardware(wallet, function(err) { + if (err) { + popupService.showAlert(gettextCatalog.getString('Error'), err.message || err); + } + }); + } + }); + }; + +}); \ No newline at end of file diff --git a/src/js/controllers/preferencesInformation.js b/src/js/controllers/preferencesInformation.js index 70ba5484e..21dc3db46 100644 --- a/src/js/controllers/preferencesInformation.js +++ b/src/js/controllers/preferencesInformation.js @@ -44,5 +44,13 @@ angular.module('copayApp.controllers').controller('preferencesInformation', $scope.M = c.m; $scope.N = c.n; $scope.pubKeys = lodash.pluck(c.publicKeyRing, 'xPubKey'); + $scope.externalSource = null; + + if (wallet.isPrivKeyExternal()) { + $scope.externalSource = lodash.find(walletService.externalSource, function(source) { + return source.id == wallet.getPrivKeyExternalSourceName(); + }).name; + } }); + }); diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 4073e08f9..b8b1a37d2 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -145,6 +145,22 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi }); }; + $scope.shouldShowReceiveAddressFromHardware = function() { + var wallet = $scope.wallet; + if (wallet.isPrivKeyExternal() && wallet.credentials.hwInfo) { + return (wallet.credentials.hwInfo.name == walletService.externalSource.intelTEE.id); + } else { + return false; + } + }; + + $scope.showReceiveAddressFromHardware = function() { + var wallet = $scope.wallet; + if (wallet.isPrivKeyExternal() && wallet.credentials.hwInfo) { + walletService.showReceiveAddressFromHardware(wallet, $scope.addr, function(){}); + } + }; + $scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.wallets = profileService.getWallets(); diff --git a/src/js/routes.js b/src/js/routes.js index 45cbc9249..2e14190c0 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -579,6 +579,15 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } } }) + .state('tabs.preferences.preferencesExternal', { + url: '/preferencesExternal', + views: { + 'tab-settings@tabs': { + controller: 'preferencesExternalController', + templateUrl: 'views/preferencesExternal.html' + } + } + }) .state('tabs.preferences.delete', { url: '/delete', views: { diff --git a/src/js/services/hwWallet.js b/src/js/services/hwWallet.js index 1c9314164..f3553bf37 100644 --- a/src/js/services/hwWallet.js +++ b/src/js/services/hwWallet.js @@ -6,9 +6,11 @@ angular.module('copayApp.services') // Ledger magic number to get xPub without user confirmation root.ENTROPY_INDEX_PATH = "0xb11e/"; + root.M = 'm/'; root.UNISIG_ROOTPATH = 44; root.MULTISIG_ROOTPATH = 48; root.LIVENET_PATH = 0; + root.TESTNET_PATH = 1; root._err = function(data) { var msg = data.error || data.message || 'unknown'; @@ -17,26 +19,49 @@ angular.module('copayApp.services') root.getRootPath = function(device, isMultisig, account) { - if (!isMultisig) return root.UNISIG_ROOTPATH; - - // Compat - if (device == 'ledger' && account == 0) return root.UNISIG_ROOTPATH; - - return root.MULTISIG_ROOTPATH; + var path; + if (isMultisig) { + path = root.MULTISIG_ROOTPATH; + } else { + if (device == 'ledger' && account > 0) { + path = root.MULTISIG_ROOTPATH; + } else { + path = root.UNISIG_ROOTPATH; + } + } + if (device == 'intelTEE') { + path = root.M + path; + } + return path; }; - root.getAddressPath = function(device, isMultisig, account) { - return root.getRootPath(device, isMultisig, account) + "'/" + root.LIVENET_PATH + "'/" + account + "'"; - } + root.getAddressPath = function(device, isMultisig, account, network) { + network = network || 'livenet'; + var networkPath = root.LIVENET_PATH; + if (network == 'testnet') { + networkPath = root.TESTNET_PATH; + } + return root.getRootPath(device, isMultisig, account) + "'/" + networkPath + "'/" + account + "'"; + }; root.getEntropyPath = function(device, isMultisig, account) { - var path; + var path = root.ENTROPY_INDEX_PATH; + if (isMultisig) { + path = path + "48'/" + } else { + path = path + "44'/" + } // Old ledger wallet compat - if (device == 'ledger' && account == 0) - return root.ENTROPY_INDEX_PATH + "0'"; + if (device == 'ledger' && account == 0) { + return path + "0'/"; + } - return root.ENTROPY_INDEX_PATH + root.getRootPath(device, isMultisig, account) + "'/" + account + "'"; + if (device == 'intelTEE') { + path = root.M + path; + } + + return path + account + "'"; }; root.pubKeyToEntropySource = function(xPubKey) { diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js new file mode 100644 index 000000000..6840d10bd --- /dev/null +++ b/src/js/services/intelTEE.js @@ -0,0 +1,191 @@ +'use strict'; + +angular.module('copayApp.services') + .factory('intelTEE', function($log, $timeout, gettext, lodash, bitcore, hwWallet, bwcService, platformInfo) { + + var root = {}; + + if (!platformInfo.isIntelTEE) { + return root; + } + + var IntelWallet = require('intelWalletCon'); + var TEE_APP_ID = '63279de1b6cb4dcf8c206716bd318092f8c206716bd31809263279de1b6cb4dc'; + + root.description = { + id: 'intelTEE', + name: 'Intel TEE', + longName: 'Intel TEE Hardware Wallet', + derivationStrategy: 'BIP44' + }; + + root.walletEnclave = new IntelWallet.Wallet(); + var walletEnclaveStatus = root.walletEnclave.initializeEnclave(); + if (walletEnclaveStatus != 0) { + $log.error('Failed to create Intel Wallet enclave'); + } + + root.getInfoForNewWallet = function(opts, callback) { + initSource(opts, function(err, opts) { + if (err) return callback(err); + + var isMultisig = opts.n > 1; + root.getEntropySource(opts.hwInfo.id, isMultisig, opts.account, function(err, entropySource) { + if (err) return callback(err); + + opts.entropySource = entropySource; + root.getXPubKey(opts.hwInfo.id, hwWallet.getAddressPath(root.description.id, isMultisig, opts.account, opts.networkName), function(data) { + if (!data.success) { + $log.warn(data.message); + return callback(data); + } + opts.extendedPublicKey = data.xpubkey; + opts.externalSource = root.description.id; + opts.derivationStrategy = root.description.derivationStrategy; + + return callback(null, opts); + }); + }); + }); + }; + + root.getXPubKey = function(teeWalletId, path, callback) { + $log.debug('TEE deriving xPub path:', path); + + // Expected to be a extended public key. + var xpubkey = root.walletEnclave.getPublicKey(teeWalletId, path); + + // Error messages returned in value. + var result = { + success: false, + message: xpubkey.ExtendedPublicKey + }; + + // Success indicated by status being equal to the tee wallet id. + if (xpubkey.Status == teeWalletId) { + result.success = true; + result.message = 'OK'; + result.xpubkey = xpubkey.ExtendedPublicKey; + } else { + $log.error('Failed to get xpubkey from TEE wallet: ' + result.message); + } + + callback(result); + }; + + root.getEntropySource = function(teeWalletId, isMultisig, account, callback) { + root.getXPubKey(teeWalletId, hwWallet.getEntropyPath(root.description.id, isMultisig, account), function(data) { + if (!data.success) + return callback(hwWallet._err(data)); + + return callback(null, hwWallet.pubKeyToEntropySource(data.xpubkey)); + }); + }; + + root.showMneumonic = function(teeWalletId, cb) { + var result = root.walletEnclave.displayWordList(teeWalletId, 'en'); + if (result != teeWalletId) { + cb(result); + } else { + cb(); + } + }; + + root.showReceiveAddress = function(teeWalletId, address, cb) { + var isMultisig = false; // TODO + var account = 0; // TODO + var basePath = hwWallet.getAddressPath(root.description.id, isMultisig, account, address.network); + var keyPath = address.path.replace('m', basePath); + + var result = root.walletEnclave.displayReceiveAddress(teeWalletId, keyPath); + if (result != teeWalletId) { + cb(result); + } else { + cb(); + } + }; + + root.signTx = function(teeWalletId, txp, callback) { + var account = 0; // TODO + var isMultisig = txp.requiredSignatures > 1; + var basePath = hwWallet.getAddressPath(root.description.id, isMultisig, account, txp.network); + + var rawTx = bwcService.Client.getRawTx(txp); + var keypaths = lodash.map(lodash.pluck(txp.inputs, 'path'), function(path) { + return path.replace('m', basePath); + }); + var publicKeys = lodash.pluck(txp.inputs, 'publicKeys'); + var changePublicKeys = txp.changeAddress.publicKeys; + publicKeys.push(changePublicKeys); + + var changeaddrpath; + if (txp.changeAddress) { + changeaddrpath = txp.changeAddress.path.replace('m', basePath); + } + + var result; + if (txp.requiredSignatures == 1) { + result = root.walletEnclave.signTransaction(teeWalletId, rawTx, changeaddrpath, keypaths); + } else { + result = root.walletEnclave.signTransaction(teeWalletId, rawTx, changeaddrpath, keypaths, publicKeys, txp.requiredSignatures, changePublicKeys, txp.requiredSignatures); + } + + if (result.Status != teeWalletId) { + return callback('TEE failed to sign transction: ' + result.Status); + } + return callback(null, result); + }; + + function initSource(opts, callback) { + var args = { + "Testnet" : (opts.networkName == 'livenet'? false : true), + "PINUnlockRequired" : false, + "PINSignatureDataRequired" : false, + "PINSignatureTransaction" : 0, + "ExportCount" : 10, + "MaxPINAttempts" : 3, + "PINTimeout" : 30 + }; + + var teeStatus = root.walletEnclave.createWallet(TEE_APP_ID, args); + switch (teeStatus) { + case "CREATE WALLET FAILURE": + case "CREATE WALLET FAILED TO INITIALIZE": + case "CREATE WALLET FAILURE BAD INPUT": + case "CREATE WALLET FAILURE case SERIALIZATION": + case "DELETE_WALLET_AUTHORIZATION_UNSUCCESSFUL": + case "LOAD_WALLET_FAILTURE": + case "IMPORT WORD LIST FAILTURE": + case "IMPORT WORD LIST FAILURE BAD INPUT": + case "IMPORT WORD NOT IN DICTIONARY": + case "INVALID PIN": + case "INVALID APPLICATION ID": + case "DISPLAY WORD LIST FAILURE": + case "DELETE WALLET NO SUCH APPLICATION ID": + case "SIGN DATA FAILURE": + case "SIGN DATA INVALID HASH": + case "SIGN DATA BUFFER TOO SMALL": + case "SIGN DATA INVALID PIN": + case "RECEIVE ADDRESS INVALID INPUT": + case "RECEIVE ADDRESS NULL": + case "RECEIVE ADDRESS BUFFER TOO SMALL": + case "PUBLIC KEY BUFFER TOO SMALL": + case "LOAD WALLET FAILURE": + case "PUBLIC KEY FAILURE": + case "PUBLIC KEY FAIL TO SERIALIZE": + case "UKNOWN ERROR CODE": + $log.error(teeStatus); + return callback(teeStatus); // TODO: translate error text for display + break; + default: + opts.hwInfo = { + name: root.description.id, + id: teeStatus + }; + $log.debug('TEE wallet created: ' + opts.hwInfo); + return callback(null, opts); + } + }; + + return root; +}); \ No newline at end of file diff --git a/src/js/services/ledger.js b/src/js/services/ledger.js index a58aa2906..3e01811b1 100644 --- a/src/js/services/ledger.js +++ b/src/js/services/ledger.js @@ -5,6 +5,12 @@ angular.module('copayApp.services') var root = {}; var LEDGER_CHROME_ID = "kkdpmhnladdopljabkgpacgpliggeeaf"; + root.description = { + id: 'ledger', + name: 'Ledger', + longName: 'Ledger Hardware Wallet' + }; + root.callbacks = {}; root.hasSession = function() { root._message({ @@ -13,7 +19,7 @@ angular.module('copayApp.services') } root.getEntropySource = function(isMultisig, account, callback) { - root.getXPubKey(hwWallet.getEntropyPath('ledger', isMultisig, account), function(data) { + root.getXPubKey(hwWallet.getEntropyPath(root.description.id, isMultisig, account), function(data) { if (!data.success) return callback(hwWallet._err(data)); @@ -30,21 +36,27 @@ angular.module('copayApp.services') }); }; - root.getInfoForNewWallet = function(isMultisig, account, callback) { - root.getEntropySource(isMultisig, account, function(err, entropySource) { + root.initSource = function(opts, callback) { + // No initialization for this hardware source. + return callback(opts); + }; + + root.getInfoForNewWallet = function(opts, callback) { + var isMultisig = opts.n > 1; + root.getEntropySource(isMultisig, opts.account, function(err, entropySource) { if (err) return callback(err); - root.getXPubKey(hwWallet.getAddressPath('ledger', isMultisig, account), function(data) { - if (!data.success) return callback(data); - - var opts = {}; - opts.entropySource = entropySource; + opts.entropySource = entropySource; + root.getXPubKey(hwWallet.getAddressPath(root.description.id, isMultisig, opts.account), function(data) { + if (!data.success) { + $log.warn(data.message); + return callback(data); + } opts.extendedPublicKey = data.xpubkey; - opts.externalSource = 'ledger'; - opts.account = account; + opts.externalSource = root.description.id; // Old ledger compat - opts.derivationStrategy = account ? 'BIP48' : 'BIP44'; + opts.derivationStrategy = opts.account ? 'BIP48' : 'BIP44'; return callback(null, opts); }); }); @@ -57,7 +69,7 @@ angular.module('copayApp.services') var tx = bwcService.getUtils().buildTx(txp); for (var i = 0; i < tx.inputs.length; i++) { redeemScripts.push(new ByteString(tx.inputs[i].redeemScript.toBuffer().toString('hex'), GP.HEX).toString()); - paths.push(hwWallet.getAddressPath('ledger', isMultisig, account) + txp.inputs[i].path.substring(1)); + paths.push(hwWallet.getAddressPath(root.description.id, isMultisig, account) + txp.inputs[i].path.substring(1)); } var splitTransaction = root._splitTransaction(new ByteString(tx.toString(), GP.HEX)); var inputs = []; diff --git a/src/js/services/platformInfo.js b/src/js/services/platformInfo.js index ee7d4c221..2a6d75aea 100644 --- a/src/js/services/platformInfo.js +++ b/src/js/services/platformInfo.js @@ -38,6 +38,7 @@ angular.module('copayApp.services').factory('platformInfo', function($window) { ret.isMobile = ret.isAndroid || ret.isIOS || ret.isWP; ret.isChromeApp = $window.chrome && chrome.runtime && chrome.runtime.id && !ret.isNW; ret.isDevel = !ret.isMobile && !ret.isChromeApp && !ret.isNW; + ret.isIntelTEE = true; return ret; }); diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index e5af8bc22..6ef9b96b0 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -347,6 +347,7 @@ angular.module('copayApp.services') account: opts.account || 0, derivationStrategy: opts.derivationStrategy || 'BIP44', }); + walletClient.credentials.hwInfo = opts.hwInfo; } catch (ex) { $log.warn("Creating wallet from Extended Public Key Arg:", ex, opts); return cb(gettextCatalog.getString('Could not create using the specified extended public key')); diff --git a/src/js/services/trezor.js b/src/js/services/trezor.js index 3a3c48215..c76860ed0 100644 --- a/src/js/services/trezor.js +++ b/src/js/services/trezor.js @@ -7,8 +7,15 @@ angular.module('copayApp.services') var SETTLE_TIME = 3000; root.callbacks = {}; + root.description = { + id: 'trezor', + name: 'Trezor', + longName: 'Trezor Hardware Wallet', + derivationStrategy: 'BIP48' + }; + root.getEntropySource = function(isMultisig, account, callback) { - root.getXPubKey(hwWallet.getEntropyPath('trezor', isMultisig, account), function(data) { + root.getXPubKey(hwWallet.getEntropyPath(root.description.id, isMultisig, account), function(data) { if (!data.success) return callback(hwWallet._err(data)); @@ -26,22 +33,25 @@ angular.module('copayApp.services') } }; + root.initSource = function(opts, callback) { + // No initialization for this hardware source. + return callback(opts); + }; - root.getInfoForNewWallet = function(isMultisig, account, callback) { - var opts = {}; - root.getEntropySource(isMultisig, account, function(err, data) { + root.getInfoForNewWallet = function(opts, callback) { + var isMultisig = opts.n > 1; + root.getEntropySource(isMultisig, opts.account, function(err, data) { if (err) return callback(err); opts.entropySource = data; $log.debug('Waiting TREZOR to settle...'); $timeout(function() { - root.getXPubKey(hwWallet.getAddressPath('trezor', isMultisig, account), function(data) { + root.getXPubKey(hwWallet.getAddressPath(root.description.id, isMultisig, opts.account), function(data) { if (!data.success) return callback(hwWallet._err(data)); opts.extendedPublicKey = data.xpubkey; - opts.externalSource = 'trezor'; - opts.account = account; + opts.externalSource = root.description.id; if (isMultisig) opts.derivationStrategy = 'BIP48'; diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index 7c3b98f07..53342286e 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -1,10 +1,16 @@ 'use strict'; -angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txFormatService, $ionicModal, $state, bwcService, bitcore, popupService) { +angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, intelTEE, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txFormatService, $ionicModal, $state, bwcService, bitcore, popupService) { // `wallet` is a decorated version of client. var root = {}; + root.externalSource = { + ledger: ledger.description, + trezor: trezor.description, + intelTEE: intelTEE.description + } + root.WALLET_STATUS_MAX_TRIES = 7; root.WALLET_STATUS_DELAY_BETWEEN_TRIES = 1.4 * 1000; root.SOFT_CONFIRMATION_LIMIT = 12; @@ -40,6 +46,40 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }); }; + var _signWithIntelTEE = function(wallet, txp, cb) { + $log.info('Requesting Intel TEE to sign the transaction'); + + intelTEE.signTx(wallet.credentials.hwInfo.id, txp, function(err, result) { + if (err) return cb(err); + + $log.debug('Intel TEE response', result); + txp.signatures = result.Signatures; + return wallet.signTxProposal(txp, cb); + }); + }; + + root.showMneumonicFromHardware = function(wallet, cb) { + switch (wallet.getPrivKeyExternalSourceName()) { + case root.externalSource.intelTEE.id: + return intelTEE.showMneumonic(wallet.credentials.hwInfo.id, cb); + break; + default: + cb('Error: unrecognized external source'); + break; + } + }; + + root.showReceiveAddressFromHardware = function(wallet, address, cb) { + switch (wallet.getPrivKeyExternalSourceName()) { + case root.externalSource.intelTEE.id: + return intelTEE.showReceiveAddress(wallet.credentials.hwInfo.id, address, cb); + break; + default: + cb('Error: unrecognized external source'); + break; + } + }; + root.invalidateCache = function(wallet) { if (wallet.cachedStatus) wallet.cachedStatus.isValid = false; @@ -629,10 +669,12 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim if (wallet.isPrivKeyExternal()) { switch (wallet.getPrivKeyExternalSourceName()) { - case 'ledger': + case root.externalSource.ledger.id: return _signWithLedger(wallet, txp, cb); - case 'trezor': + case root.externalSource.trezor.id: return _signWithTrezor(wallet, txp, cb); + case root.externalSource.intelTEE.id: + return _signWithIntelTEE(wallet, txp, cb); default: var msg = 'Unsupported External Key:' + wallet.getPrivKeyExternalSourceName(); $log.error(msg); diff --git a/www/img/icon-inteltee-white.svg b/www/img/icon-inteltee-white.svg new file mode 100644 index 000000000..92f9bc4ba --- /dev/null +++ b/www/img/icon-inteltee-white.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + ® + \ No newline at end of file diff --git a/www/views/includes/walletInfo.html b/www/views/includes/walletInfo.html index d4f1fbc17..7b149060e 100644 --- a/www/views/includes/walletInfo.html +++ b/www/views/includes/walletInfo.html @@ -4,7 +4,13 @@
Auditable - + + + +#{{wallet.account || 0}} diff --git a/www/views/preferences.html b/www/views/preferences.html index 5d21e1193..fda6f20d7 100644 --- a/www/views/preferences.html +++ b/www/views/preferences.html @@ -18,12 +18,6 @@ - - Hardware Wallet - - {{externalSource}} - - Color diff --git a/www/views/preferencesExternal.html b/www/views/preferencesExternal.html new file mode 100644 index 000000000..651a394e4 --- /dev/null +++ b/www/views/preferencesExternal.html @@ -0,0 +1,14 @@ + + + {{exteralSource}} + + + + +
+ +
+
+
diff --git a/www/views/preferencesInformation.html b/www/views/preferencesInformation.html index bdf2ca9df..060ae55a8 100644 --- a/www/views/preferencesInformation.html +++ b/www/views/preferencesInformation.html @@ -43,6 +43,13 @@ {{derivationStrategy}}
+ + Hardware Wallet + + {{externalSource}} + + +
Hardware Wallet diff --git a/www/views/tab-create-shared.html b/www/views/tab-create-shared.html index 3f9d25811..4b3100247 100644 --- a/www/views/tab-create-shared.html +++ b/www/views/tab-create-shared.html @@ -120,7 +120,7 @@ ng-model="formData.derivationPath"> - + Testnet diff --git a/www/views/tab-import-hardware.html b/www/views/tab-import-hardware.html index 7f750182b..07c715315 100644 --- a/www/views/tab-import-hardware.html +++ b/www/views/tab-import-hardware.html @@ -15,7 +15,7 @@ -
+ + + +
+ +
+
+ +
From 8d63fa35075dea5e5c972f96f86fcbdc6d9c0f97 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Thu, 16 Mar 2017 14:37:41 -0400 Subject: [PATCH 02/12] Improve detection of supported hw wallets. --- src/js/controllers/create.js | 22 +++++++++++----------- src/js/controllers/join.js | 9 +++------ src/js/services/intelTEE.js | 15 ++++++++------- src/js/services/ledger.js | 3 ++- src/js/services/platformInfo.js | 5 ++++- src/js/services/trezor.js | 3 ++- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index 6316fd4f8..343422369 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -1,11 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('createController', - function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService) { - - var isChromeApp = platformInfo.isChromeApp; - var isCordova = platformInfo.isCordova; - var isDevel = platformInfo.isDevel; + function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService) { /* For compressed keys, m*73 + n*34 <= 496 */ var COPAYER_PAIR_LIMITS = { @@ -67,9 +63,6 @@ angular.module('copayApp.controllers').controller('createController', var seedOptions = [{ id: 'new', label: gettextCatalog.getString('Random'), - }, { - id: walletService.externalSource.intelTEE.id, - label: gettextCatalog(walletService.externalSource.intelTEE.name), }, { id: 'set', label: gettextCatalog.getString('Specify Recovery Phrase...'), @@ -84,18 +77,25 @@ angular.module('copayApp.controllers').controller('createController', */ if (appConfigService.name == 'copay') { - if (n > 1 && isChromeApp) + if (n > 1 && walletService.externalSource.ledger.supported) seedOptions.push({ id: walletService.externalSource.ledger.id, label: walletService.externalSource.ledger.longName, }); - if (isChromeApp || isDevel) { + if (walletService.externalSource.trezor.supported) { seedOptions.push({ id: walletService.externalSource.trezor.id, label: walletService.externalSource.trezor.longName, }); } + + if (walletService.externalSource.intelTEE.supported) { + seedOptions.push({ + id: walletService.externalSource.intelTEE.id, + label: walletService.externalSource.intelTEE.longName, + }); + } } $scope.seedOptions = seedOptions; @@ -179,7 +179,7 @@ angular.module('copayApp.controllers').controller('createController', src = intelTEE; break; default: - this.error = gettextCatalog('Invalid seed source id: ' + self.seedSourceId); + this.error = gettextCatalog.getString('Invalid seed source id: ' + self.seedSourceId); return; } diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index 3bbf4813b..73f3281bf 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -1,10 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('joinController', - function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) { - - var isChromeApp = platformInfo.isChromeApp; - var isDevel = platformInfo.isDevel; + function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) { var self = this; var defaults = configService.getDefaults(); @@ -64,14 +61,14 @@ angular.module('copayApp.controllers').controller('joinController', */ if (appConfigService.name == 'copay') { - if (isChromeApp) { + if (walletService.externalSource.ledger.supported) { self.seedOptions.push({ id: walletService.externalSource.ledger.id, label: walletService.externalSource.ledger.longName, }); } - if (isChromeApp || isDevel) { + if (walletService.externalSource.trezor.supported) { self.seedOptions.push({ id: walletService.externalSource.trezor.id, label: walletService.externalSource.trezor.longName, diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js index 6840d10bd..74ffd7734 100644 --- a/src/js/services/intelTEE.js +++ b/src/js/services/intelTEE.js @@ -5,20 +5,21 @@ angular.module('copayApp.services') var root = {}; - if (!platformInfo.isIntelTEE) { - return root; - } - - var IntelWallet = require('intelWalletCon'); - var TEE_APP_ID = '63279de1b6cb4dcf8c206716bd318092f8c206716bd31809263279de1b6cb4dc'; - root.description = { + supports: platformInfo.supportsIntelTEE, id: 'intelTEE', name: 'Intel TEE', longName: 'Intel TEE Hardware Wallet', derivationStrategy: 'BIP44' }; + if (!root.description.isAvailable) { + return root; + } + + var IntelWallet = require('intelWalletCon'); + var TEE_APP_ID = '63279de1b6cb4dcf8c206716bd318092f8c206716bd31809263279de1b6cb4dc'; + root.walletEnclave = new IntelWallet.Wallet(); var walletEnclaveStatus = root.walletEnclave.initializeEnclave(); if (walletEnclaveStatus != 0) { diff --git a/src/js/services/ledger.js b/src/js/services/ledger.js index 3e01811b1..d28df597f 100644 --- a/src/js/services/ledger.js +++ b/src/js/services/ledger.js @@ -1,11 +1,12 @@ 'use strict'; angular.module('copayApp.services') - .factory('ledger', function($log, bwcService, gettext, hwWallet) { + .factory('ledger', function($log, bwcService, gettext, hwWallet, platformInfo) { var root = {}; var LEDGER_CHROME_ID = "kkdpmhnladdopljabkgpacgpliggeeaf"; root.description = { + supports: platformInfo.supportsLedger, id: 'ledger', name: 'Ledger', longName: 'Ledger Hardware Wallet' diff --git a/src/js/services/platformInfo.js b/src/js/services/platformInfo.js index 2a6d75aea..459e96167 100644 --- a/src/js/services/platformInfo.js +++ b/src/js/services/platformInfo.js @@ -38,7 +38,10 @@ angular.module('copayApp.services').factory('platformInfo', function($window) { ret.isMobile = ret.isAndroid || ret.isIOS || ret.isWP; ret.isChromeApp = $window.chrome && chrome.runtime && chrome.runtime.id && !ret.isNW; ret.isDevel = !ret.isMobile && !ret.isChromeApp && !ret.isNW; - ret.isIntelTEE = true; + + ret.supportsLedger = ret.isChromeApp; + ret.supportsTrezor = ret.isChromeApp || ret.isDevel; + ret.supportsIntelTEE = false; return ret; }); diff --git a/src/js/services/trezor.js b/src/js/services/trezor.js index c76860ed0..407d94c4b 100644 --- a/src/js/services/trezor.js +++ b/src/js/services/trezor.js @@ -1,13 +1,14 @@ 'use strict'; angular.module('copayApp.services') - .factory('trezor', function($log, $timeout, lodash, bitcore, hwWallet) { + .factory('trezor', function($log, $timeout, lodash, bitcore, hwWallet, platformInfo) { var root = {}; var SETTLE_TIME = 3000; root.callbacks = {}; root.description = { + supported: platformInfo.supportsTrezor, id: 'trezor', name: 'Trezor', longName: 'Trezor Hardware Wallet', From 80d2b7bc0198ba950c3912ec50a3f7db3aafe4d8 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Thu, 16 Mar 2017 15:29:37 -0400 Subject: [PATCH 03/12] Detect Windows platform for TEE. --- src/js/services/platformInfo.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/services/platformInfo.js b/src/js/services/platformInfo.js index 459e96167..f0a0d774c 100644 --- a/src/js/services/platformInfo.js +++ b/src/js/services/platformInfo.js @@ -38,10 +38,11 @@ angular.module('copayApp.services').factory('platformInfo', function($window) { ret.isMobile = ret.isAndroid || ret.isIOS || ret.isWP; ret.isChromeApp = $window.chrome && chrome.runtime && chrome.runtime.id && !ret.isNW; ret.isDevel = !ret.isMobile && !ret.isChromeApp && !ret.isNW; + ret.isWindows = navigator.platform.indexOf('Win') > -1; ret.supportsLedger = ret.isChromeApp; ret.supportsTrezor = ret.isChromeApp || ret.isDevel; - ret.supportsIntelTEE = false; + ret.supportsIntelTEE = ret.isWindows; // TODO need to detect specific chip set for TEE support return ret; }); From 2153d9b4684a2fdf8ea00589401167c54526eee6 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Thu, 16 Mar 2017 15:37:10 -0400 Subject: [PATCH 04/12] Fix hw descriptions. --- src/js/services/intelTEE.js | 2 +- src/js/services/ledger.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js index 74ffd7734..ea75cb872 100644 --- a/src/js/services/intelTEE.js +++ b/src/js/services/intelTEE.js @@ -6,7 +6,7 @@ angular.module('copayApp.services') var root = {}; root.description = { - supports: platformInfo.supportsIntelTEE, + supported: platformInfo.supportsIntelTEE, id: 'intelTEE', name: 'Intel TEE', longName: 'Intel TEE Hardware Wallet', diff --git a/src/js/services/ledger.js b/src/js/services/ledger.js index d28df597f..df3ac4972 100644 --- a/src/js/services/ledger.js +++ b/src/js/services/ledger.js @@ -6,7 +6,7 @@ angular.module('copayApp.services') var LEDGER_CHROME_ID = "kkdpmhnladdopljabkgpacgpliggeeaf"; root.description = { - supports: platformInfo.supportsLedger, + supported: platformInfo.supportsLedger, id: 'ledger', name: 'Ledger', longName: 'Ledger Hardware Wallet' From e6d997a701b0b854dbe0177c9d05742f6653dcc2 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Fri, 17 Mar 2017 17:00:26 -0400 Subject: [PATCH 05/12] Provide address object to intel tee service to display address securely. --- src/js/services/walletService.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index 53342286e..558f422a2 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -72,7 +72,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim root.showReceiveAddressFromHardware = function(wallet, address, cb) { switch (wallet.getPrivKeyExternalSourceName()) { case root.externalSource.intelTEE.id: - return intelTEE.showReceiveAddress(wallet.credentials.hwInfo.id, address, cb); + root.getAddressObj(wallet, address, function(err, addrObj) { + if (err) return cb(err); + return intelTEE.showReceiveAddress(wallet.credentials.hwInfo.id, addrObj, cb); + }); break; default: cb('Error: unrecognized external source'); @@ -887,6 +890,21 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }); }; + root.getAddressObj = function(wallet, address, cb) { + wallet.getMainAddresses({ + reverse: true + }, function(err, addr) { + if (err) return cb(err); + var addrObj = lodash.find(addr, function(a) { + return a.address == address; + }); + var err = null; + if (!addrObj) { + err = 'Error: specified address not in wallet'; + } + return cb(err, addrObj); + }); + }; root.isReady = function(wallet, cb) { if (!wallet.isComplete()) From 8c00fe27aa9b32de2c593ae88682e54b71d9a81c Mon Sep 17 00:00:00 2001 From: Gabrielbazan7 Date: Fri, 17 Mar 2017 18:23:50 -0400 Subject: [PATCH 06/12] Bug fixes after rebase. Please enter the commit message for your changes. Lines starting --- src/js/controllers/create.js | 10 +++++----- src/js/controllers/preferencesExternal.js | 2 +- src/js/controllers/preferencesInformation.js | 2 +- src/js/services/intelTEE.js | 2 +- src/sass/views/tab-receive.scss | 11 +++++++++++ www/views/preferencesExternal.html | 2 +- www/views/preferencesInformation.html | 6 ------ www/views/tab-receive.html | 12 ++---------- 8 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index 343422369..da3a2c9c4 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -154,23 +154,23 @@ angular.module('copayApp.controllers').controller('createController', return; } - if ($scope.seedSource.id == walletService.externalSource.ledger.id || $scope.seedSource.id == walletService.externalSource.trezor.id || self.seedSourceId == walletService.externalSource.intelTEE.id) { + if ($scope.seedSource.id == walletService.externalSource.ledger.id || $scope.seedSource.id == walletService.externalSource.trezor.id || $scope.seedSource.id == walletService.externalSource.intelTEE.id) { var account = $scope.formData.account; if (!account || account < 1) { popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); return; } - if ($scope.seedSource.id == walletService.externalSource.trezor.id || self.seedSource.id == walletService.externalSource.intelTEE.id) + if ($scope.seedSource.id == walletService.externalSource.trezor.id || $scope.seedSource.id == walletService.externalSource.intelTEE.id) account = account - 1; opts.account = account; ongoingProcess.set('connecting' + $scope.seedSource.id, true); var src; - switch (self.seedSourceId) { + switch ($scope.seedSource.id) { case walletService.externalSource.ledger.id: - src = legder; + src = ledger; break; case walletService.externalSource.trezor.id: src = trezor; @@ -179,7 +179,7 @@ angular.module('copayApp.controllers').controller('createController', src = intelTEE; break; default: - this.error = gettextCatalog.getString('Invalid seed source id: ' + self.seedSourceId); + this.error = gettextCatalog.getString('Invalid seed source id: ' + $scope.seedSource.id); return; } diff --git a/src/js/controllers/preferencesExternal.js b/src/js/controllers/preferencesExternal.js index 9be05b92f..12ea10a7d 100644 --- a/src/js/controllers/preferencesExternal.js +++ b/src/js/controllers/preferencesExternal.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('preferencesExternalController', function($scope, lodash, profileService, walletService) { +angular.module('copayApp.controllers').controller('preferencesExternalController', function($scope, $stateParams, lodash, gettextCatalog, popupService, profileService, walletService) { var wallet = profileService.getWallet($stateParams.walletId); $scope.externalSource = lodash.find(walletService.externalSource, function(source) { diff --git a/src/js/controllers/preferencesInformation.js b/src/js/controllers/preferencesInformation.js index 21dc3db46..9362d883f 100644 --- a/src/js/controllers/preferencesInformation.js +++ b/src/js/controllers/preferencesInformation.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('preferencesInformation', - function($scope, $log, $ionicHistory, platformInfo, lodash, profileService, configService, $stateParams, $state) { + function($scope, $log, $ionicHistory, platformInfo, lodash, profileService, configService, $stateParams, $state, walletService) { var wallet = profileService.getWallet($stateParams.walletId); $scope.wallet = wallet; diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js index ea75cb872..0b5724fe2 100644 --- a/src/js/services/intelTEE.js +++ b/src/js/services/intelTEE.js @@ -13,7 +13,7 @@ angular.module('copayApp.services') derivationStrategy: 'BIP44' }; - if (!root.description.isAvailable) { + if (!root.description.supported) { return root; } diff --git a/src/sass/views/tab-receive.scss b/src/sass/views/tab-receive.scss index 2228ed07a..483f988c3 100644 --- a/src/sass/views/tab-receive.scss +++ b/src/sass/views/tab-receive.scss @@ -162,6 +162,17 @@ transform: translate(100%, -40%); } } + .overlay { + position: absolute; + width: 220px; + height: 100%; + background-color: rgba(255,255,255,0.8); + button { + width: 100%; + top: 50%; + transform: translateY(-50%); + } + } @media(max-height: 700px) { padding: 10vh 0 4vh; } diff --git a/www/views/preferencesExternal.html b/www/views/preferencesExternal.html index 651a394e4..719a0d448 100644 --- a/www/views/preferencesExternal.html +++ b/www/views/preferencesExternal.html @@ -1,6 +1,6 @@ - {{exteralSource}} + {{externalSource}} diff --git a/www/views/preferencesInformation.html b/www/views/preferencesInformation.html index 060ae55a8..3e1bcd4ff 100644 --- a/www/views/preferencesInformation.html +++ b/www/views/preferencesInformation.html @@ -50,12 +50,6 @@ -
- Hardware Wallet - - {{wallet.getPrivKeyExternalSourceName()}} - -
diff --git a/www/views/tab-receive.html b/www/views/tab-receive.html index 0683ecbe2..644af8e0f 100644 --- a/www/views/tab-receive.html +++ b/www/views/tab-receive.html @@ -53,19 +53,11 @@
- - - -
- -
- -
From 80f3b70784c04c2c39f72fe95d1e53ef71aea228 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Tue, 21 Mar 2017 10:09:50 -0400 Subject: [PATCH 07/12] Implement intel tee version detection. --- src/js/controllers/preferencesExternal.js | 2 +- src/js/services/intelTEE.js | 1 + src/js/services/platformInfo.js | 26 +++++++++++++++++++++-- www/views/preferencesExternal.html | 11 +++++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/js/controllers/preferencesExternal.js b/src/js/controllers/preferencesExternal.js index 12ea10a7d..ebc10043e 100644 --- a/src/js/controllers/preferencesExternal.js +++ b/src/js/controllers/preferencesExternal.js @@ -5,7 +5,7 @@ angular.module('copayApp.controllers').controller('preferencesExternalController $scope.externalSource = lodash.find(walletService.externalSource, function(source) { return source.id == wallet.getPrivKeyExternalSourceName(); - }).name; + }); $scope.showMneumonicFromHardwarePopup = function() { var title = gettextCatalog.getString('Warning!'); diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js index 0b5724fe2..a7e459ae7 100644 --- a/src/js/services/intelTEE.js +++ b/src/js/services/intelTEE.js @@ -7,6 +7,7 @@ angular.module('copayApp.services') root.description = { supported: platformInfo.supportsIntelTEE, + version: platformInfo.versionIntelTEE, id: 'intelTEE', name: 'Intel TEE', longName: 'Intel TEE Hardware Wallet', diff --git a/src/js/services/platformInfo.js b/src/js/services/platformInfo.js index f0a0d774c..8396afa07 100644 --- a/src/js/services/platformInfo.js +++ b/src/js/services/platformInfo.js @@ -23,6 +23,27 @@ angular.module('copayApp.services').factory('platformInfo', function($window) { } }; + var getVersionIntelTee = function() { + var v = ''; + var isWindows = navigator.platform.indexOf('Win') > -1; + + if (!isNodeWebkit() || !isWindows) { + return v; + } + + try { + var IntelWallet = require('intelWalletCon'); + if (IntelWallet.getVersion) { + v = IntelWallet.getVersion(); + } else { + v = 'Alpha'; + } + if (v.length > 0) { + $log.info('Intel TEE library ' + v); + } + } catch (e) {} + return v; + }; // Detect mobile devices var ret = { @@ -38,11 +59,12 @@ angular.module('copayApp.services').factory('platformInfo', function($window) { ret.isMobile = ret.isAndroid || ret.isIOS || ret.isWP; ret.isChromeApp = $window.chrome && chrome.runtime && chrome.runtime.id && !ret.isNW; ret.isDevel = !ret.isMobile && !ret.isChromeApp && !ret.isNW; - ret.isWindows = navigator.platform.indexOf('Win') > -1; ret.supportsLedger = ret.isChromeApp; ret.supportsTrezor = ret.isChromeApp || ret.isDevel; - ret.supportsIntelTEE = ret.isWindows; // TODO need to detect specific chip set for TEE support + + ret.versionIntelTEE = getVersionIntelTee(); + ret.supportsIntelTEE = ret.versionIntelTEE.length > 0; return ret; }); diff --git a/www/views/preferencesExternal.html b/www/views/preferencesExternal.html index 719a0d448..0703932d1 100644 --- a/www/views/preferencesExternal.html +++ b/www/views/preferencesExternal.html @@ -1,10 +1,19 @@ - {{externalSource}} + {{externalSource.longName}} +
+
+ Version + + {{externalSource.version}} + +
+
+
+
+
+
+ Version + + {{externalSource.version || 'hardware disconnected'}} + +
+
+ +
+ +
From c0e90ac21ab36b1916b1bc05d543a9985abb4783 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Tue, 21 Mar 2017 11:48:55 -0400 Subject: [PATCH 09/12] Revert BWS version. --- app-template/package-template.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-template/package-template.json b/app-template/package-template.json index 054526a24..c6b567f25 100644 --- a/app-template/package-template.json +++ b/app-template/package-template.json @@ -56,7 +56,7 @@ "bezier-easing": "^2.0.3", "bhttp": "^1.2.1", "bitauth": "https://github.com/gabrielbazan7/bitauth.git#copay", - "bitcore-wallet-client": "git://github.com/isocolsky/bitcore-wallet-client#369eaede49cd64836015fb9b8a502092ee84dc7c", + "bitcore-wallet-client": "5.1.2", "bower": "^1.7.9", "cordova-android": "5.1.1", "cordova-custom-config": "^3.0.5", From 413990f94c6a05a5c75be2a7cb532690b0a7b372 Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Fri, 7 Apr 2017 10:54:30 -0400 Subject: [PATCH 10/12] Bug fixes - ledger testing --- src/js/controllers/create.js | 2 +- src/js/controllers/import.js | 2 +- src/js/controllers/join.js | 1 + src/js/controllers/preferencesExternal.js | 30 ++++++++-------- src/js/services/intelTEE.js | 11 +++--- src/js/services/ledger.js | 11 +++--- src/js/services/trezor.js | 11 +++--- www/views/includes/walletInfo.html | 13 +++---- www/views/preferencesExternal.html | 42 ++++++++++++++--------- 9 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index da3a2c9c4..bbf4d992a 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -183,7 +183,7 @@ angular.module('copayApp.controllers').controller('createController', return; } - src.getInfoForNewWallet(opts, function(err, lopts) { + src.getInfoForNewWallet(opts.n > 1, account, function(err, lopts) { ongoingProcess.set('connecting' + $scope.seedSource.id, false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 4964058ef..e34546d9e 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -35,7 +35,7 @@ angular.module('copayApp.controllers').controller('importController', if ($scope.isChromeApp || $scope.isDevel) { $scope.seedOptions.push({ id: walletService.externalSource.trezor.id, - label: walletService.externalSource.ledger.longName, + label: walletService.externalSource.trezor.longName, }); $scope.formData.seedSource = $scope.seedOptions[0]; } diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index 73f3281bf..6800fc9fc 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -138,6 +138,7 @@ angular.module('copayApp.controllers').controller('joinController', account = account - 1; opts.account = account; + opts.isMultisig = true; ongoingProcess.set('connecting' + self.seedSourceId, true); var src = self.seedSourceId == walletService.externalSource.ledger.id ? ledger : trezor; diff --git a/src/js/controllers/preferencesExternal.js b/src/js/controllers/preferencesExternal.js index 6be633901..c44c0af6c 100644 --- a/src/js/controllers/preferencesExternal.js +++ b/src/js/controllers/preferencesExternal.js @@ -8,20 +8,22 @@ angular.module('copayApp.controllers').controller('preferencesExternalController return source.id == wallet.getPrivKeyExternalSourceName(); }); - $scope.hardwareConnected = $scope.externalSource.version.length > 0; + if ($scope.externalSource.hasEmbeddedHardware) { + $scope.hardwareConnected = $scope.externalSource.version.length > 0; - $scope.showMneumonicFromHardwarePopup = function() { - var title = gettextCatalog.getString('Warning!'); - var message = gettextCatalog.getString('Are you being watched? Anyone with your recovery phrase can access or spend your bitcoin.'); - popupService.showConfirm(title, message, null, null, function(res) { - if (res) { - walletService.showMneumonicFromHardware(wallet, function(err) { - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err.message || err); - } - }); - } - }); - }; + $scope.showMneumonicFromHardwarePopup = function() { + var title = gettextCatalog.getString('Warning!'); + var message = gettextCatalog.getString('Are you being watched? Anyone with your recovery phrase can access or spend your bitcoin.'); + popupService.showConfirm(title, message, null, null, function(res) { + if (res) { + walletService.showMneumonicFromHardware(wallet, function(err) { + if (err) { + popupService.showAlert(gettextCatalog.getString('Error'), err.message || err); + } + }); + } + }); + }; + } }); \ No newline at end of file diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js index a7e459ae7..36dbc5181 100644 --- a/src/js/services/intelTEE.js +++ b/src/js/services/intelTEE.js @@ -11,7 +11,8 @@ angular.module('copayApp.services') id: 'intelTEE', name: 'Intel TEE', longName: 'Intel TEE Hardware Wallet', - derivationStrategy: 'BIP44' + derivationStrategy: 'BIP44', + hasEmbeddedHardware: true }; if (!root.description.supported) { @@ -27,16 +28,16 @@ angular.module('copayApp.services') $log.error('Failed to create Intel Wallet enclave'); } - root.getInfoForNewWallet = function(opts, callback) { + root.getInfoForNewWallet = function(isMultisig, account, callback) { + var opts = {}; initSource(opts, function(err, opts) { if (err) return callback(err); - var isMultisig = opts.n > 1; - root.getEntropySource(opts.hwInfo.id, isMultisig, opts.account, function(err, entropySource) { + root.getEntropySource(opts.hwInfo.id, isMultisig, account, function(err, entropySource) { if (err) return callback(err); opts.entropySource = entropySource; - root.getXPubKey(opts.hwInfo.id, hwWallet.getAddressPath(root.description.id, isMultisig, opts.account, opts.networkName), function(data) { + root.getXPubKey(opts.hwInfo.id, hwWallet.getAddressPath(root.description.id, isMultisig, account, opts.networkName), function(data) { if (!data.success) { $log.warn(data.message); return callback(data); diff --git a/src/js/services/ledger.js b/src/js/services/ledger.js index df3ac4972..5336f39ce 100644 --- a/src/js/services/ledger.js +++ b/src/js/services/ledger.js @@ -9,7 +9,8 @@ angular.module('copayApp.services') supported: platformInfo.supportsLedger, id: 'ledger', name: 'Ledger', - longName: 'Ledger Hardware Wallet' + longName: 'Ledger Hardware Wallet', + hasEmbeddedHardware: false }; root.callbacks = {}; @@ -42,13 +43,13 @@ angular.module('copayApp.services') return callback(opts); }; - root.getInfoForNewWallet = function(opts, callback) { - var isMultisig = opts.n > 1; - root.getEntropySource(isMultisig, opts.account, function(err, entropySource) { + root.getInfoForNewWallet = function(isMultisig, account, callback) { + root.getEntropySource(isMultisig, account, function(err, entropySource) { if (err) return callback(err); + var opts = {}; opts.entropySource = entropySource; - root.getXPubKey(hwWallet.getAddressPath(root.description.id, isMultisig, opts.account), function(data) { + root.getXPubKey(hwWallet.getAddressPath(root.description.id, isMultisig, account), function(data) { if (!data.success) { $log.warn(data.message); return callback(data); diff --git a/src/js/services/trezor.js b/src/js/services/trezor.js index 407d94c4b..c3c406866 100644 --- a/src/js/services/trezor.js +++ b/src/js/services/trezor.js @@ -12,7 +12,8 @@ angular.module('copayApp.services') id: 'trezor', name: 'Trezor', longName: 'Trezor Hardware Wallet', - derivationStrategy: 'BIP48' + derivationStrategy: 'BIP48', + hasEmbeddedHardware: false }; root.getEntropySource = function(isMultisig, account, callback) { @@ -39,15 +40,15 @@ angular.module('copayApp.services') return callback(opts); }; - root.getInfoForNewWallet = function(opts, callback) { - var isMultisig = opts.n > 1; - root.getEntropySource(isMultisig, opts.account, function(err, data) { + root.getInfoForNewWallet = function(isMultisig, account, callback) { + var opts = {}; + root.getEntropySource(isMultisig, account, function(err, data) { if (err) return callback(err); opts.entropySource = data; $log.debug('Waiting TREZOR to settle...'); $timeout(function() { - root.getXPubKey(hwWallet.getAddressPath(root.description.id, isMultisig, opts.account), function(data) { + root.getXPubKey(hwWallet.getAddressPath(root.description.id, isMultisig, account), function(data) { if (!data.success) return callback(hwWallet._err(data)); diff --git a/www/views/includes/walletInfo.html b/www/views/includes/walletInfo.html index 7b149060e..98ec7ac02 100644 --- a/www/views/includes/walletInfo.html +++ b/www/views/includes/walletInfo.html @@ -4,16 +4,11 @@
Auditable - - - -#{{wallet.account || 0}} + - - + + + {{wallet.m}}-of-{{wallet.n}} #{{wallet.credentials.account || 0}} diff --git a/www/views/preferencesExternal.html b/www/views/preferencesExternal.html index beb4db140..bfb3562ad 100644 --- a/www/views/preferencesExternal.html +++ b/www/views/preferencesExternal.html @@ -6,26 +6,36 @@
-
- Hardware not connected.
- Check installation and retry. + +
+
+ No hardware information available. +
-
-
-
- Version - - {{externalSource.version || 'hardware disconnected'}} - +
+
+ Hardware not connected.
+ Check installation and retry. +
+ +
+
+
+ Version + + {{externalSource.version || 'hardware disconnected'}} + +
+
+ +
+
- -
- -
+ From 36cb23015af63fedd8863e45e0339cf2216677a9 Mon Sep 17 00:00:00 2001 From: Gabrielbazan7 Date: Fri, 7 Apr 2017 17:12:02 -0400 Subject: [PATCH 11/12] Bug fixes - retest intel tee. --- src/js/controllers/create.js | 11 ++++++++--- src/js/controllers/import.js | 4 ++-- src/js/controllers/join.js | 2 +- src/js/controllers/preferencesExternal.js | 2 +- src/js/services/intelTEE.js | 9 +++++---- src/js/services/ledger.js | 6 ++++-- src/js/services/trezor.js | 6 ++++-- www/views/preferencesExternal.html | 4 ++-- www/views/tab-create-personal.html | 2 +- www/views/tab-create-shared.html | 2 +- 10 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index bbf4d992a..1e54684ed 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -63,9 +63,11 @@ angular.module('copayApp.controllers').controller('createController', var seedOptions = [{ id: 'new', label: gettextCatalog.getString('Random'), + supportsTestnet: true }, { id: 'set', label: gettextCatalog.getString('Specify Recovery Phrase...'), + supportsTestnet: false }]; $scope.seedSource = seedOptions[0]; @@ -81,12 +83,14 @@ angular.module('copayApp.controllers').controller('createController', seedOptions.push({ id: walletService.externalSource.ledger.id, label: walletService.externalSource.ledger.longName, + supportsTestnet: walletService.externalSource.ledger.supportsTestnet }); if (walletService.externalSource.trezor.supported) { seedOptions.push({ id: walletService.externalSource.trezor.id, label: walletService.externalSource.trezor.longName, + supportsTestnet: walletService.externalSource.trezor.supportsTestnet }); } @@ -94,6 +98,7 @@ angular.module('copayApp.controllers').controller('createController', seedOptions.push({ id: walletService.externalSource.intelTEE.id, label: walletService.externalSource.intelTEE.longName, + supportsTestnet: walletService.externalSource.intelTEE.supportsTestnet }); } } @@ -165,7 +170,7 @@ angular.module('copayApp.controllers').controller('createController', account = account - 1; opts.account = account; - ongoingProcess.set('connecting' + $scope.seedSource.id, true); + ongoingProcess.set('connecting ' + $scope.seedSource.id, true); var src; switch ($scope.seedSource.id) { @@ -183,8 +188,8 @@ angular.module('copayApp.controllers').controller('createController', return; } - src.getInfoForNewWallet(opts.n > 1, account, function(err, lopts) { - ongoingProcess.set('connecting' + $scope.seedSource.id, false); + src.getInfoForNewWallet(opts.n > 1, account, opts.networkName, function(err, lopts) { + ongoingProcess.set('connecting ' + $scope.seedSource.id, false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); return; diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index e34546d9e..3776671ee 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -262,7 +262,7 @@ angular.module('copayApp.controllers').controller('importController', }; $scope.importTrezor = function(account, isMultisig) { - trezor.getInfoForNewWallet(isMultisig, account, function(err, lopts) { + trezor.getInfoForNewWallet(isMultisig, account, 'livenet', function(err, lopts) { ongoingProcess.clear(); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); @@ -318,7 +318,7 @@ angular.module('copayApp.controllers').controller('importController', }; $scope.importLedger = function(account) { - ledger.getInfoForNewWallet(true, account, function(err, lopts) { + ledger.getInfoForNewWallet(true, account, 'livenet', function(err, lopts) { ongoingProcess.clear(); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index 6800fc9fc..b2e858969 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -142,7 +142,7 @@ angular.module('copayApp.controllers').controller('joinController', ongoingProcess.set('connecting' + self.seedSourceId, true); var src = self.seedSourceId == walletService.externalSource.ledger.id ? ledger : trezor; - src.getInfoForNewWallet(true, account, function(err, lopts) { + src.getInfoForNewWallet(true, account, 'livenet', function(err, lopts) { ongoingProcess.set('connecting' + self.seedSourceId, false); if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); diff --git a/src/js/controllers/preferencesExternal.js b/src/js/controllers/preferencesExternal.js index c44c0af6c..3f7366f1f 100644 --- a/src/js/controllers/preferencesExternal.js +++ b/src/js/controllers/preferencesExternal.js @@ -8,7 +8,7 @@ angular.module('copayApp.controllers').controller('preferencesExternalController return source.id == wallet.getPrivKeyExternalSourceName(); }); - if ($scope.externalSource.hasEmbeddedHardware) { + if ($scope.externalSource.isEmbeddedHardware) { $scope.hardwareConnected = $scope.externalSource.version.length > 0; $scope.showMneumonicFromHardwarePopup = function() { diff --git a/src/js/services/intelTEE.js b/src/js/services/intelTEE.js index 36dbc5181..39859c863 100644 --- a/src/js/services/intelTEE.js +++ b/src/js/services/intelTEE.js @@ -12,7 +12,8 @@ angular.module('copayApp.services') name: 'Intel TEE', longName: 'Intel TEE Hardware Wallet', derivationStrategy: 'BIP44', - hasEmbeddedHardware: true + isEmbeddedHardware: true, + supportsTestnet: true }; if (!root.description.supported) { @@ -28,7 +29,7 @@ angular.module('copayApp.services') $log.error('Failed to create Intel Wallet enclave'); } - root.getInfoForNewWallet = function(isMultisig, account, callback) { + root.getInfoForNewWallet = function(isMultisig, account, networkName, callback) { var opts = {}; initSource(opts, function(err, opts) { if (err) return callback(err); @@ -37,7 +38,7 @@ angular.module('copayApp.services') if (err) return callback(err); opts.entropySource = entropySource; - root.getXPubKey(opts.hwInfo.id, hwWallet.getAddressPath(root.description.id, isMultisig, account, opts.networkName), function(data) { + root.getXPubKey(opts.hwInfo.id, hwWallet.getAddressPath(root.description.id, isMultisig, account, networkName), function(data) { if (!data.success) { $log.warn(data.message); return callback(data); @@ -185,7 +186,7 @@ angular.module('copayApp.services') name: root.description.id, id: teeStatus }; - $log.debug('TEE wallet created: ' + opts.hwInfo); + $log.debug('TEE wallet created: ' + opts.hwInfo.id); return callback(null, opts); } }; diff --git a/src/js/services/ledger.js b/src/js/services/ledger.js index 5336f39ce..abfe6c8f7 100644 --- a/src/js/services/ledger.js +++ b/src/js/services/ledger.js @@ -10,7 +10,8 @@ angular.module('copayApp.services') id: 'ledger', name: 'Ledger', longName: 'Ledger Hardware Wallet', - hasEmbeddedHardware: false + isEmbeddedHardware: false, + supportsTestnet: false }; root.callbacks = {}; @@ -43,7 +44,8 @@ angular.module('copayApp.services') return callback(opts); }; - root.getInfoForNewWallet = function(isMultisig, account, callback) { + root.getInfoForNewWallet = function(isMultisig, account, networkName, callback) { + // networkName not used for this hardware (always livenet) root.getEntropySource(isMultisig, account, function(err, entropySource) { if (err) return callback(err); diff --git a/src/js/services/trezor.js b/src/js/services/trezor.js index c3c406866..0411386fc 100644 --- a/src/js/services/trezor.js +++ b/src/js/services/trezor.js @@ -13,7 +13,8 @@ angular.module('copayApp.services') name: 'Trezor', longName: 'Trezor Hardware Wallet', derivationStrategy: 'BIP48', - hasEmbeddedHardware: false + isEmbeddedHardware: false, + supportsTestnet: false }; root.getEntropySource = function(isMultisig, account, callback) { @@ -40,7 +41,8 @@ angular.module('copayApp.services') return callback(opts); }; - root.getInfoForNewWallet = function(isMultisig, account, callback) { + root.getInfoForNewWallet = function(isMultisig, account, networkName, callback) { + // networkName not used for this hardware (always livenet) var opts = {}; root.getEntropySource(isMultisig, account, function(err, data) { if (err) return callback(err); diff --git a/www/views/preferencesExternal.html b/www/views/preferencesExternal.html index bfb3562ad..22ae4f276 100644 --- a/www/views/preferencesExternal.html +++ b/www/views/preferencesExternal.html @@ -7,13 +7,13 @@
-
+
No hardware information available.
-
+
Hardware not connected.
Check installation and retry. diff --git a/www/views/tab-create-personal.html b/www/views/tab-create-personal.html index 21794f56a..e532165c9 100644 --- a/www/views/tab-create-personal.html +++ b/www/views/tab-create-personal.html @@ -90,7 +90,7 @@ ng-model="formData.derivationPath"> - + Testnet diff --git a/www/views/tab-create-shared.html b/www/views/tab-create-shared.html index 4b3100247..edd6f8175 100644 --- a/www/views/tab-create-shared.html +++ b/www/views/tab-create-shared.html @@ -120,7 +120,7 @@ ng-model="formData.derivationPath"> - + Testnet From a742e538141f909cfeead672f31d00979868457e Mon Sep 17 00:00:00 2001 From: Andy Phillipson Date: Mon, 17 Apr 2017 10:55:16 -0400 Subject: [PATCH 12/12] Review and test fixes. --- src/js/controllers/import.js | 10 +++--- src/js/controllers/join.js | 37 ++++++++++++++++++----- src/js/controllers/preferencesExternal.js | 1 - www/views/import.html | 2 +- www/views/preferences.html | 2 +- www/views/preferencesInformation.html | 8 ++++- 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 3776671ee..c5657d5cf 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -3,15 +3,13 @@ angular.module('copayApp.controllers').controller('importController', function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, profileService, configService, sjcl, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess, walletService, popupService, gettextCatalog, appConfigService) { - var isChromeApp = platformInfo.isChromeApp; - var isDevel = platformInfo.isDevel; var reader = new FileReader(); var defaults = configService.getDefaults(); var errors = bwcService.getErrors(); $scope.init = function() { - $scope.isDevel = platformInfo.isDevel; - $scope.isChromeApp = platformInfo.isChromeApp; + $scope.supportsLedger = platformInfo.supportsLedger; + $scope.supportsTrezor = platformInfo.supportsTrezor; $scope.isCordova = platformInfo.isCordova; $scope.formData = {}; $scope.formData.bwsurl = defaults.bws.url; @@ -25,14 +23,14 @@ angular.module('copayApp.controllers').controller('importController', $scope.seedOptions = []; - if ($scope.isChromeApp) { + if ($scope.supportsLedger) { $scope.seedOptions.push({ id: walletService.externalSource.ledger.id, label: walletService.externalSource.ledger.longName, }); } - if ($scope.isChromeApp || $scope.isDevel) { + if ($scope.supportsTrezor) { $scope.seedOptions.push({ id: walletService.externalSource.trezor.id, label: walletService.externalSource.trezor.longName, diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index b2e858969..0f416f0ea 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('joinController', - function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) { + function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) { var self = this; var defaults = configService.getDefaults(); @@ -64,14 +64,21 @@ angular.module('copayApp.controllers').controller('joinController', if (walletService.externalSource.ledger.supported) { self.seedOptions.push({ id: walletService.externalSource.ledger.id, - label: walletService.externalSource.ledger.longName, + label: walletService.externalSource.ledger.longName }); } if (walletService.externalSource.trezor.supported) { self.seedOptions.push({ id: walletService.externalSource.trezor.id, - label: walletService.externalSource.trezor.longName, + label: walletService.externalSource.trezor.longName + }); + } + + if (walletService.externalSource.intelTEE.supported) { + seedOptions.push({ + id: walletService.externalSource.intelTEE.id, + label: walletService.externalSource.intelTEE.longName }); } } @@ -94,7 +101,7 @@ angular.module('copayApp.controllers').controller('joinController', var opts = { secret: form.secret.$modelValue, myName: form.myName.$modelValue, - bwsurl: $scope.bwsurl, + bwsurl: $scope.bwsurl } var setSeed = self.seedSourceId == 'set'; @@ -127,21 +134,37 @@ angular.module('copayApp.controllers').controller('joinController', return; } - if (self.seedSourceId == walletService.externalSource.ledger.id || self.seedSourceId == walletService.externalSource.trezor.id) { + if (self.seedSourceId == walletService.externalSource.ledger.id || self.seedSourceId == walletService.externalSource.trezor.id || self.seedSourceId == walletService.externalSource.intelTEE.id) { var account = $scope.account; if (!account || account < 1) { popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); return; } - if (self.seedSourceId == walletService.externalSource.trezor.id) + if (self.seedSourceId == walletService.externalSource.trezor.id || self.seedSourceId == walletService.externalSource.intelTEE.id) account = account - 1; opts.account = account; opts.isMultisig = true; ongoingProcess.set('connecting' + self.seedSourceId, true); - var src = self.seedSourceId == walletService.externalSource.ledger.id ? ledger : trezor; + var src; + switch (self.seedSourceId) { + case walletService.externalSource.ledger.id: + src = ledger; + break; + case walletService.externalSource.trezor.id: + src = trezor; + break; + case walletService.externalSource.intelTEE.id: + src = intelTEE; + break; + default: + this.error = gettextCatalog.getString('Invalid seed source id: ' + self.seedSourceId); + return; + } + + // TODO: cannot currently join an intelTEE testnet wallet (need to detect from the secret) src.getInfoForNewWallet(true, account, 'livenet', function(err, lopts) { ongoingProcess.set('connecting' + self.seedSourceId, false); if (err) { diff --git a/src/js/controllers/preferencesExternal.js b/src/js/controllers/preferencesExternal.js index 3f7366f1f..916dc0e60 100644 --- a/src/js/controllers/preferencesExternal.js +++ b/src/js/controllers/preferencesExternal.js @@ -2,7 +2,6 @@ angular.module('copayApp.controllers').controller('preferencesExternalController', function($scope, $stateParams, lodash, gettextCatalog, popupService, profileService, walletService) { var wallet = profileService.getWallet($stateParams.walletId); - $scope.wallet = wallet; $scope.externalSource = lodash.find(walletService.externalSource, function(source) { return source.id == wallet.getPrivKeyExternalSourceName(); diff --git a/www/views/import.html b/www/views/import.html index 6baf86f06..973bd6ebb 100644 --- a/www/views/import.html +++ b/www/views/import.html @@ -16,7 +16,7 @@ File/Text
+ {'border-bottom-style': 'solid'}" ng-show="isCopay && (supportsLedger || supportsTrezor)"> Hardware wallet
diff --git a/www/views/preferences.html b/www/views/preferences.html index fda6f20d7..5c8d6f7aa 100644 --- a/www/views/preferences.html +++ b/www/views/preferences.html @@ -32,7 +32,7 @@ Hide Balance - - +
+ Hardware Wallet + + {{externalSource}} + +
+
Hardware Wallet {{externalSource}}