2015-03-06 12:00:10 -03:00
'use strict' ;
2015-11-18 18:37:42 -03:00
angular . module ( 'copayApp.controllers' ) . controller ( 'backupController' ,
2017-11-13 16:49:59 +09:00
function ( $scope , $timeout , $log , $state , $stateParams , $ionicHistory , lodash , profileService , bwcService , walletService , ongoingProcess , popupService , gettextCatalog , $ionicModal , firebaseEventsService ) {
2018-01-16 11:36:52 +09:00
if ( $state . current . name == 'onboarding.backup' ) {
$scope . onboarding = true ;
}
2017-11-30 14:36:31 +09:00
if ( $stateParams . bchWalletId && $stateParams . btcWalletId ) {
$scope . wallet = profileService . getWallet ( $stateParams . bchWalletId ) ;
$scope . btcWallet = profileService . getWallet ( $stateParams . btcWalletId ) ;
} else {
$scope . wallet = profileService . getWallet ( $stateParams . walletId ) ;
}
2017-01-26 17:42:39 -03:00
$scope . viewTitle = $scope . wallet . name || $scope . wallet . credentials . walletName ;
$scope . n = $scope . wallet . n ;
2016-08-29 16:22:54 -03:00
var keys ;
2016-08-19 14:38:28 -03:00
2017-01-26 17:42:39 -03:00
$scope . credentialsEncrypted = $scope . wallet . isPrivKeyEncrypted ( ) ;
2015-11-23 17:53:42 -03:00
2016-08-25 16:31:47 -03:00
var isDeletedSeed = function ( ) {
2017-01-26 17:42:39 -03:00
if ( ! $scope . wallet . credentials . mnemonic && ! $scope . wallet . credentials . mnemonicEncrypted )
2016-08-25 16:31:47 -03:00
return true ;
2016-08-29 16:22:54 -03:00
2016-08-25 16:31:47 -03:00
return false ;
} ;
var shuffledWords = function ( words ) {
2016-06-16 14:43:10 -03:00
var sort = lodash . sortBy ( words ) ;
2015-11-30 17:30:26 -03:00
2016-06-16 14:43:10 -03:00
return lodash . map ( sort , function ( w ) {
return {
word : w ,
selected : false
} ;
} ) ;
} ;
2016-08-25 16:31:47 -03:00
2016-10-07 17:32:52 -03:00
$scope . setFlow = function ( step ) {
2016-08-29 16:22:54 -03:00
if ( ! keys ) return ;
2016-06-16 14:43:10 -03:00
2016-08-29 16:13:18 -03:00
var words = keys . mnemonic ;
2016-09-13 17:00:27 -03:00
$scope . data = { } ;
2016-06-16 14:43:10 -03:00
$scope . mnemonicWords = words . split ( /[\u3000\s]+/ ) ;
2016-06-13 16:13:35 -03:00
$scope . shuffledMnemonicWords = shuffledWords ( $scope . mnemonicWords ) ;
2017-01-26 17:42:39 -03:00
$scope . mnemonicHasPassphrase = $scope . wallet . mnemonicHasPassphrase ( ) ;
2016-06-16 14:43:10 -03:00
$scope . useIdeograms = words . indexOf ( "\u3000" ) >= 0 ;
2016-09-13 17:00:27 -03:00
$scope . data . passphrase = null ;
2016-06-13 16:13:35 -03:00
$scope . customWords = [ ] ;
2016-10-07 17:32:52 -03:00
$scope . step = step || 1 ;
2016-06-13 16:13:35 -03:00
$scope . selectComplete = false ;
$scope . backupError = false ;
2016-06-16 13:53:44 -03:00
2016-08-29 11:58:23 -03:00
words = lodash . repeat ( 'x' , 300 ) ;
2016-06-16 14:43:10 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
} , 10 ) ;
2016-05-30 13:37:15 -03:00
} ;
2016-08-25 16:31:47 -03:00
var backupError = function ( err ) {
ongoingProcess . set ( 'validatingWords' , false ) ;
$log . debug ( 'Failed to verify backup: ' , err ) ;
$scope . backupError = true ;
2015-11-20 14:38:29 -03:00
2016-09-13 14:05:49 -04:00
$timeout ( function ( ) {
2016-08-25 16:31:47 -03:00
$scope . $apply ( ) ;
} , 1 ) ;
2016-05-24 13:19:13 -03:00
} ;
2015-11-20 14:38:29 -03:00
2016-09-13 17:00:27 -03:00
function openConfirmBackupModal ( ) {
$ionicModal . fromTemplateUrl ( 'views/includes/confirmBackupPopup.html' , {
scope : $scope ,
backdropClickToClose : false ,
hardwareBackButtonClose : false
} ) . then ( function ( modal ) {
$scope . confirmBackupModal = modal ;
$scope . confirmBackupModal . show ( ) ;
} ) ;
2016-09-13 14:26:25 -04:00
} ;
2016-08-25 16:31:47 -03:00
2016-09-13 17:00:27 -03:00
var showBackupResult = function ( ) {
2016-09-09 11:14:04 -03:00
if ( $scope . backupError ) {
2016-12-13 12:08:05 -03:00
var title = gettextCatalog . getString ( 'Uh oh...' ) ;
2016-10-07 02:10:30 -04:00
var message = gettextCatalog . getString ( "It's important that you write your backup phrase down correctly. If something happens to your wallet, you'll need this backup to recover your money. Please review your backup and try again." ) ;
2016-09-09 11:14:04 -03:00
popupService . showAlert ( title , message , function ( ) {
2016-10-07 17:32:52 -03:00
$scope . setFlow ( 2 ) ;
2016-09-09 11:14:04 -03:00
} )
2016-09-13 17:00:27 -03:00
} else {
2017-11-13 16:49:59 +09:00
firebaseEventsService . logEvent ( 'backed_up_wallet' ) ;
2016-09-13 17:00:27 -03:00
openConfirmBackupModal ( ) ;
2016-09-09 11:14:04 -03:00
}
2016-09-13 17:00:27 -03:00
} ;
$scope . closeBackupResultModal = function ( ) {
$scope . confirmBackupModal . hide ( ) ;
2016-09-29 14:50:33 -04:00
$scope . confirmBackupModal . remove ( ) ;
2018-02-02 12:27:32 -04:00
$state . go ( 'tabs.home' ) ;
2016-09-13 17:00:27 -03:00
} ;
2015-11-20 14:38:29 -03:00
2017-02-16 16:41:36 -05:00
$scope . copyRecoveryPhrase = function ( ) {
if ( $scope . wallet . network == 'livenet' ) return null ;
else if ( ! $scope . wallet . credentials . mnemonic ) return null ;
else return $scope . wallet . credentials . mnemonic ;
} ;
2016-08-25 16:31:47 -03:00
var confirm = function ( cb ) {
2016-06-13 16:13:35 -03:00
$scope . backupError = false ;
2015-11-20 14:38:29 -03:00
2016-06-13 16:13:35 -03:00
var customWordList = lodash . pluck ( $scope . customWords , 'word' ) ;
2015-11-20 14:38:29 -03:00
2016-06-13 16:13:35 -03:00
if ( ! lodash . isEqual ( $scope . mnemonicWords , customWordList ) ) {
2016-06-09 14:50:58 -03:00
return cb ( 'Mnemonic string mismatch' ) ;
2015-11-20 14:38:29 -03:00
}
2016-06-09 14:50:58 -03:00
$timeout ( function ( ) {
2016-06-13 16:13:35 -03:00
if ( $scope . mnemonicHasPassphrase ) {
2016-06-09 14:50:58 -03:00
var walletClient = bwcService . getClient ( ) ;
2016-06-13 16:13:35 -03:00
var separator = $scope . useIdeograms ? '\u3000' : ' ' ;
2016-06-09 14:50:58 -03:00
var customSentence = customWordList . join ( separator ) ;
2016-09-13 17:00:27 -03:00
var passphrase = $scope . data . passphrase || '' ;
2016-06-09 14:50:58 -03:00
try {
walletClient . seedFromMnemonic ( customSentence , {
2017-01-26 17:42:39 -03:00
network : $scope . wallet . credentials . network ,
2016-06-09 14:50:58 -03:00
passphrase : passphrase ,
2017-01-26 17:42:39 -03:00
account : $scope . wallet . credentials . account
2016-06-09 14:50:58 -03:00
} ) ;
} catch ( err ) {
2016-08-29 11:58:23 -03:00
walletClient . credentials . xPrivKey = lodash . repeat ( 'x' , 64 ) ;
2016-06-09 14:50:58 -03:00
return cb ( err ) ;
}
2016-08-29 16:22:54 -03:00
if ( walletClient . credentials . xPrivKey . substr ( walletClient . credentials . xPrivKey ) != keys . xPrivKey ) {
2016-08-29 16:13:18 -03:00
delete walletClient . credentials ;
2016-06-09 14:50:58 -03:00
return cb ( 'Private key mismatch' ) ;
}
2016-06-09 14:45:28 -03:00
}
2015-11-30 17:30:26 -03:00
2017-01-26 17:42:39 -03:00
profileService . setBackupFlag ( $scope . wallet . credentials . walletId ) ;
2017-11-30 14:36:31 +09:00
if ( $scope . btcWallet ) {
profileService . setBackupFlag ( $scope . btcWallet . credentials . walletId ) ;
}
2016-08-30 17:07:49 -03:00
return cb ( ) ;
2016-06-09 14:50:58 -03:00
} , 1 ) ;
2016-05-24 13:19:13 -03:00
} ;
2015-11-30 17:30:26 -03:00
2016-08-25 16:31:47 -03:00
var finalStep = function ( ) {
ongoingProcess . set ( 'validatingWords' , true ) ;
confirm ( function ( err ) {
ongoingProcess . set ( 'validatingWords' , false ) ;
if ( err ) {
backupError ( err ) ;
}
$timeout ( function ( ) {
2016-09-13 17:00:27 -03:00
showBackupResult ( ) ;
2016-08-25 16:31:47 -03:00
return ;
} , 1 ) ;
} ) ;
} ;
$scope . goToStep = function ( n ) {
if ( n == 1 )
2016-10-07 17:32:52 -03:00
$scope . setFlow ( ) ;
2016-08-25 16:31:47 -03:00
if ( n == 2 )
$scope . step = 2 ;
if ( n == 3 ) {
if ( ! $scope . mnemonicHasPassphrase )
finalStep ( ) ;
else
$scope . step = 3 ;
2016-06-16 14:43:10 -03:00
}
2016-08-25 16:31:47 -03:00
if ( n == 4 )
2016-09-13 14:05:49 -04:00
finalStep ( ) ;
2016-08-25 16:31:47 -03:00
} ;
2016-06-16 14:43:10 -03:00
2016-08-25 16:31:47 -03:00
$scope . addButton = function ( index , item ) {
var newWord = {
word : item . word ,
prevIndex : index
} ;
$scope . customWords . push ( newWord ) ;
$scope . shuffledMnemonicWords [ index ] . selected = true ;
$scope . shouldContinue ( ) ;
2016-06-16 14:43:10 -03:00
} ;
2016-08-25 16:31:47 -03:00
$scope . removeButton = function ( index , item ) {
if ( $scope . loading ) return ;
$scope . customWords . splice ( index , 1 ) ;
$scope . shuffledMnemonicWords [ item . prevIndex ] . selected = false ;
$scope . shouldContinue ( ) ;
} ;
2015-11-30 17:30:26 -03:00
2016-08-25 16:31:47 -03:00
$scope . shouldContinue = function ( ) {
if ( $scope . customWords . length == $scope . shuffledMnemonicWords . length )
$scope . selectComplete = true ;
else
$scope . selectComplete = false ;
2015-11-30 17:30:26 -03:00
} ;
2016-08-25 16:31:47 -03:00
2016-09-22 17:04:49 -03:00
$scope . $on ( "$ionicView.enter" , function ( event , data ) {
2016-09-22 10:34:00 -03:00
$scope . deleted = isDeletedSeed ( ) ;
if ( $scope . deleted ) {
$log . debug ( 'no mnemonics' ) ;
return ;
}
2017-01-26 17:42:39 -03:00
walletService . getKeys ( $scope . wallet , function ( err , k ) {
2016-09-22 10:34:00 -03:00
if ( err || ! k ) {
$log . error ( 'Could not get keys: ' , err ) ;
2016-10-07 10:31:10 -03:00
$ionicHistory . goBack ( ) ;
2016-09-22 10:34:00 -03:00
return ;
}
$scope . credentialsEncrypted = false ;
keys = k ;
2016-10-07 17:32:52 -03:00
$scope . setFlow ( ) ;
2016-09-22 10:34:00 -03:00
} ) ;
} ) ;
2016-10-07 02:10:30 -04:00
} ) ;