2017-02-17 13:36:51 -03:00
'use strict' ;
2017-06-15 19:30:28 -03:00
angular . module ( 'copayApp.controllers' ) . controller ( 'topUpController' , function ( $scope , $log , $state , $timeout , $ionicHistory , $ionicConfig , lodash , popupService , profileService , ongoingProcess , walletService , configService , platformInfo , bitpayService , bitpayCardService , payproService , bwcError , txFormatService , sendMaxService , gettextCatalog ) {
2017-02-17 13:36:51 -03:00
2017-06-15 19:30:28 -03:00
var dataSrc = { } ;
2017-02-17 13:36:51 -03:00
var cardId ;
2017-04-16 22:23:20 -03:00
var sendMax ;
2017-06-15 19:30:28 -03:00
var configWallet = configService . getSync ( ) . wallet ;
2017-05-15 14:26:49 -03:00
2017-04-20 13:27:15 -03:00
var showErrorAndBack = function ( title , msg ) {
2017-06-15 19:30:28 -03:00
title = title || gettextCatalog . getString ( 'Error' ) ;
2017-02-17 13:36:51 -03:00
$scope . sendStatus = '' ;
2017-04-20 13:27:15 -03:00
$log . error ( msg ) ;
msg = msg . errors ? msg . errors [ 0 ] . message : msg ;
popupService . showAlert ( title , msg , function ( ) {
2017-02-17 13:36:51 -03:00
$ionicHistory . goBack ( ) ;
} ) ;
} ;
2017-03-20 14:53:18 -03:00
var showError = function ( title , msg ) {
2017-06-15 19:30:28 -03:00
title = title || gettextCatalog . getString ( 'Error' ) ;
2017-02-17 13:36:51 -03:00
$scope . sendStatus = '' ;
2017-03-20 14:53:18 -03:00
$log . error ( msg ) ;
msg = msg . errors ? msg . errors [ 0 ] . message : msg ;
popupService . showAlert ( title , msg ) ;
2017-02-17 13:36:51 -03:00
} ;
var publishAndSign = function ( wallet , txp , onSendStatusChange , cb ) {
if ( ! wallet . canSign ( ) && ! wallet . isPrivKeyExternal ( ) ) {
2017-06-15 19:30:28 -03:00
var err = gettextCatalog . getString ( 'No signing proposal: No private key' ) ;
2017-02-17 13:36:51 -03:00
$log . info ( err ) ;
return cb ( err ) ;
}
walletService . publishAndSign ( wallet , txp , function ( err , txp ) {
if ( err ) return cb ( err ) ;
return cb ( null , txp ) ;
} , onSendStatusChange ) ;
} ;
var statusChangeHandler = function ( processName , showName , isOn ) {
$log . debug ( 'statusChangeHandler: ' , processName , showName , isOn ) ;
2017-06-15 19:30:28 -03:00
if ( processName == 'sendingTx' && ! isOn ) {
2017-02-17 13:36:51 -03:00
$scope . sendStatus = 'success' ;
$timeout ( function ( ) {
$scope . $digest ( ) ;
} , 100 ) ;
} else if ( showName ) {
$scope . sendStatus = showName ;
}
} ;
2017-06-15 19:30:28 -03:00
var createInvoice = function ( ) {
$scope . expirationTime = null ;
ongoingProcess . set ( 'creatingInvoice' , true ) ;
bitpayCardService . topUp ( cardId , dataSrc , function ( err , invoiceId ) {
if ( err ) {
ongoingProcess . set ( 'creatingInvoice' , false ) ;
showErrorAndBack ( gettextCatalog . getString ( 'Could not create the invoice' ) , err ) ;
return ;
}
bitpayCardService . getInvoice ( invoiceId , function ( err , inv ) {
ongoingProcess . set ( 'creatingInvoice' , false ) ;
if ( err ) {
showError ( gettextCatalog . getString ( 'Could not get the invoice' ) , err ) ;
return ;
}
$scope . invoice = inv ;
$scope . expirationTime = ( $scope . invoice . expirationTime - $scope . invoice . invoiceTime ) / 1000 ;
$timeout ( function ( ) {
$scope . $digest ( ) ;
} , 1 ) ;
} ) ;
} ) ;
} ;
$scope . $on ( "$ionicView.beforeLeave" , function ( event , data ) {
$ionicConfig . views . swipeBackEnabled ( true ) ;
} ) ;
$scope . $on ( "$ionicView.enter" , function ( event , data ) {
$ionicConfig . views . swipeBackEnabled ( false ) ;
} ) ;
2017-02-17 13:36:51 -03:00
$scope . $on ( "$ionicView.beforeEnter" , function ( event , data ) {
2017-06-15 19:30:28 -03:00
$scope . wallet = null ;
$scope . isCordova = platformInfo . isCordova ;
2017-02-17 13:36:51 -03:00
cardId = data . stateParams . id ;
2017-04-16 22:23:20 -03:00
sendMax = data . stateParams . useSendMax ;
2017-02-17 13:36:51 -03:00
if ( ! cardId ) {
2017-06-15 19:30:28 -03:00
showErrorAndBack ( null , gettextCatalog . getString ( 'No card selected' ) ) ;
2017-02-17 13:36:51 -03:00
return ;
}
2017-06-15 19:30:28 -03:00
2017-03-27 11:31:46 -03:00
var parsedAmount = txFormatService . parseAmount (
2017-06-15 19:30:28 -03:00
data . stateParams . amount ,
2017-02-17 13:36:51 -03:00
data . stateParams . currency ) ;
2017-06-15 19:30:28 -03:00
dataSrc [ 'amount' ] = parsedAmount . amount ;
dataSrc [ 'currency' ] = parsedAmount . currency ;
2017-02-17 13:36:51 -03:00
$scope . amountUnitStr = parsedAmount . amountUnitStr ;
$scope . network = bitpayService . getEnvironment ( ) . network ;
$scope . wallets = profileService . getWallets ( {
onlyComplete : true ,
2017-03-20 14:53:18 -03:00
network : $scope . network ,
hasFunds : true ,
minAmount : parsedAmount . amountSat
2017-02-17 13:36:51 -03:00
} ) ;
2017-03-20 14:53:18 -03:00
if ( lodash . isEmpty ( $scope . wallets ) ) {
2017-06-15 19:30:28 -03:00
showErrorAndBack ( null , gettextCatalog . getString ( 'Insufficient funds' ) ) ;
2017-03-20 14:53:18 -03:00
return ;
}
$scope . onWalletSelect ( $scope . wallets [ 0 ] ) ; // Default first wallet
2017-02-17 13:36:51 -03:00
bitpayCardService . get ( { cardId : cardId , noRefresh : true } , function ( err , card ) {
if ( err ) {
2017-04-20 13:27:15 -03:00
showErrorAndBack ( null , err ) ;
2017-02-17 13:36:51 -03:00
return ;
}
$scope . cardInfo = card [ 0 ] ;
2017-06-05 12:09:48 -03:00
bitpayCardService . setCurrencySymbol ( $scope . cardInfo ) ;
bitpayCardService . getRates ( $scope . cardInfo . currency , function ( err , data ) {
if ( err ) $log . error ( err ) ;
$scope . rate = data . rate ;
} ) ;
2017-02-17 13:36:51 -03:00
} ) ;
} ) ;
$scope . topUpConfirm = function ( ) {
2017-06-15 19:30:28 -03:00
var title ;
var message = gettextCatalog . getString ( "Top up {{amountStr}} to debit card ({{cardLastNumber}})" , {
amountStr : $scope . amountUnitStr ,
cardLastNumber : $scope . cardInfo . lastFourDigits
} ) ;
var okText = gettextCatalog . getString ( 'Continue' ) ;
var cancelText = gettextCatalog . getString ( 'Cancel' ) ;
popupService . showConfirm ( title , message , okText , cancelText , function ( ok ) {
2017-02-17 13:36:51 -03:00
if ( ! ok ) return ;
ongoingProcess . set ( 'topup' , true , statusChangeHandler ) ;
2017-06-15 19:30:28 -03:00
var payProUrl = ( $scope . invoice && $scope . invoice . paymentUrls ) ? $scope . invoice . paymentUrls . BIP73 : null ;
if ( ! payProUrl ) {
ongoingProcess . set ( 'topup' , false , statusChangeHandler ) ;
showError ( gettextCatalog . getString ( 'Error in Payment Protocol' ) , gettextCatalog . getString ( 'Invalid URL' ) ) ;
return ;
}
payproService . getPayProDetails ( payProUrl , function ( err , payProDetails ) {
2017-02-17 13:36:51 -03:00
if ( err ) {
ongoingProcess . set ( 'topup' , false , statusChangeHandler ) ;
2017-06-15 19:30:28 -03:00
showError ( gettextCatalog . getString ( 'Error fetching invoice' ) , err ) ;
2017-02-17 13:36:51 -03:00
return ;
}
2017-06-15 19:30:28 -03:00
var outputs = [ ] ;
var toAddress = payProDetails . toAddress ;
var amountSat = payProDetails . amount ;
2017-02-17 13:36:51 -03:00
2017-06-15 19:30:28 -03:00
outputs . push ( {
'toAddress' : toAddress ,
'amount' : amountSat ,
'message' : message
} ) ;
2017-02-17 13:36:51 -03:00
2017-06-15 19:30:28 -03:00
var txp = {
toAddress : toAddress ,
amount : amountSat ,
outputs : outputs ,
message : message ,
payProUrl : payProUrl ,
excludeUnconfirmedUtxos : configWallet . spendUnconfirmed ? false : true ,
feeLevel : configWallet . settings . feeLevel || 'normal'
} ;
walletService . createTx ( $scope . wallet , txp , function ( err , ctxp ) {
if ( err ) {
2017-02-17 13:36:51 -03:00
ongoingProcess . set ( 'topup' , false , statusChangeHandler ) ;
2017-06-15 19:30:28 -03:00
showError ( gettextCatalog . getString ( 'Could not create transaction' ) , bwcError . msg ( err ) ) ;
2017-02-17 13:36:51 -03:00
return ;
}
2017-06-15 19:42:00 -03:00
title = gettextCatalog . getString ( 'Sending {{amountStr}} from {{walletName}}' , {
2017-06-15 19:30:28 -03:00
amountStr : txFormatService . formatAmountStr ( ctxp . amount , true ) ,
2017-06-15 19:42:00 -03:00
walletName : $scope . wallet . name
2017-06-15 19:30:28 -03:00
} ) ;
message = gettextCatalog . getString ( "{{fee}} will be deducted for bitcoin networking fees." , {
fee : txFormatService . formatAmountStr ( ctxp . fee )
} ) ;
okText = gettextCatalog . getString ( 'Confirm' ) ;
popupService . showConfirm ( title , message , okText , cancelText , function ( ok ) {
ongoingProcess . set ( 'topup' , false , statusChangeHandler ) ;
if ( ! ok ) {
$scope . sendStatus = '' ;
2017-02-17 13:36:51 -03:00
return ;
}
2017-06-15 19:30:28 -03:00
$scope . expirationTime = null ; // Disable countdown
ongoingProcess . set ( 'sendingTx' , true , statusChangeHandler ) ;
publishAndSign ( $scope . wallet , ctxp , function ( ) { } , function ( err , txSent ) {
ongoingProcess . set ( 'sendingTx' , false , statusChangeHandler ) ;
2017-02-17 13:36:51 -03:00
if ( err ) {
2017-06-15 19:30:28 -03:00
showError ( gettextCatalog . getString ( 'Could not send transaction' ) , err ) ;
2017-02-17 13:36:51 -03:00
return ;
}
} ) ;
2017-06-15 19:30:28 -03:00
} ) ;
2017-02-17 13:36:51 -03:00
} ) ;
2017-06-15 19:30:28 -03:00
} , true ) ; // Disable loader
} ) ;
2017-02-17 13:36:51 -03:00
} ;
$scope . showWalletSelector = function ( ) {
$scope . walletSelectorTitle = 'From' ;
$scope . showWallets = true ;
} ;
$scope . onWalletSelect = function ( wallet ) {
2017-06-15 19:30:28 -03:00
if ( $scope . wallet && ( wallet . id == $scope . wallet . id ) ) return ;
2017-02-17 13:36:51 -03:00
$scope . wallet = wallet ;
2017-04-16 22:23:20 -03:00
if ( sendMax ) {
ongoingProcess . set ( 'retrievingInputs' , true ) ;
sendMaxService . getInfo ( $scope . wallet , function ( err , values ) {
ongoingProcess . set ( 'retrievingInputs' , false ) ;
if ( err ) {
2017-04-20 13:27:15 -03:00
showErrorAndBack ( null , err ) ;
2017-04-16 22:23:20 -03:00
return ;
}
2017-06-15 19:30:28 -03:00
var unitName = configWallet . settings . unitName ;
2017-04-16 22:23:20 -03:00
var amountUnit = txFormatService . satToUnit ( values . amount ) ;
var parsedAmount = txFormatService . parseAmount (
2017-06-15 19:30:28 -03:00
amountUnit ,
2017-04-16 22:23:20 -03:00
unitName ) ;
2017-06-15 19:30:28 -03:00
dataSrc [ 'amount' ] = parsedAmount . amount ;
dataSrc [ 'currency' ] = parsedAmount . currency ;
2017-04-16 22:23:20 -03:00
$scope . amountUnitStr = parsedAmount . amountUnitStr ;
2017-06-15 19:30:28 -03:00
createInvoice ( ) ;
2017-04-16 22:23:20 -03:00
$timeout ( function ( ) {
$scope . $digest ( ) ;
} , 100 ) ;
} ) ;
2017-06-15 19:30:28 -03:00
} else {
createInvoice ( ) ;
2017-04-16 22:23:20 -03:00
}
2017-02-17 13:36:51 -03:00
} ;
2017-06-15 19:30:28 -03:00
$scope . invoiceExpired = function ( ) {
$scope . sendStatus = '' ;
showErrorAndBack ( gettextCatalog . getString ( 'Invoice Expired' ) , gettextCatalog . getString ( 'This invoice has expired. An invoice is only valid for 15 minutes.' ) ) ;
} ;
2017-02-17 13:36:51 -03:00
$scope . goBackHome = function ( ) {
$scope . sendStatus = '' ;
$ionicHistory . nextViewOptions ( {
disableAnimate : true ,
historyRoot : true
} ) ;
$ionicHistory . clearHistory ( ) ;
$state . go ( 'tabs.home' ) . then ( function ( ) {
$state . transitionTo ( 'tabs.bitpayCard' , { id : cardId } ) ;
} ) ;
} ;
} ) ;