2016-08-16 18:38:18 -03:00
'use strict' ;
2016-12-02 14:48:39 -03:00
angular . module ( 'copayApp.controllers' ) . controller ( 'confirmController' , function ( $rootScope , $scope , $interval , $filter , $timeout , $ionicScrollDelegate , gettextCatalog , walletService , platformInfo , lodash , configService , rateService , $stateParams , $window , $state , $log , profileService , bitcore , gettext , txFormatService , ongoingProcess , $ionicModal , popupService , $ionicHistory , $ionicConfig , payproService , feeService , amazonService , glideraService , bwcError ) {
2016-08-18 14:51:35 -03:00
var cachedTxp = { } ;
2016-11-23 11:23:19 -03:00
var toAmount ;
2016-08-24 19:12:11 -03:00
var isChromeApp = platformInfo . isChromeApp ;
2016-10-20 15:38:57 -03:00
var countDown = null ;
2016-11-29 21:49:56 -03:00
var giftCardAmountUSD ;
var giftCardAccessKey ;
var giftCardInvoiceTime ;
var giftCardUUID ;
2016-11-25 15:59:44 -03:00
var cachedSendMax = { } ;
2016-11-01 18:56:30 -03:00
$scope . isCordova = platformInfo . isCordova ;
2016-10-10 10:56:12 -04:00
$ionicConfig . views . swipeBackEnabled ( false ) ;
2016-09-29 10:10:53 -03:00
$scope . $on ( "$ionicView.beforeEnter" , function ( event , data ) {
2016-11-29 21:49:56 -03:00
// Amazon.com Gift Card parameters
$scope . isGiftCard = data . stateParams . isGiftCard ;
giftCardAmountUSD = data . stateParams . giftCardAmountUSD ;
giftCardAccessKey = data . stateParams . giftCardAccessKey ;
giftCardInvoiceTime = data . stateParams . giftCardInvoiceTime ;
giftCardUUID = data . stateParams . giftCardUUID ;
2016-12-02 09:48:56 -03:00
// Glidera parameters
2016-12-02 10:09:24 -03:00
$scope . isGlidera = data . stateParams . isGlidera ;
$scope . glideraAccessToken = data . stateParams . glideraAccessToken ;
2016-12-02 09:48:56 -03:00
2016-11-23 11:23:19 -03:00
toAmount = data . stateParams . toAmount ;
2016-11-29 11:05:55 -03:00
cachedSendMax = { } ;
2016-11-25 15:59:44 -03:00
$scope . useSendMax = data . stateParams . useSendMax == 'true' ? true : false ;
2016-09-28 17:51:45 -03:00
$scope . isWallet = data . stateParams . isWallet ;
2016-10-06 19:23:39 -03:00
$scope . cardId = data . stateParams . cardId ;
2016-09-28 17:51:45 -03:00
$scope . toAddress = data . stateParams . toAddress ;
$scope . toName = data . stateParams . toName ;
$scope . toEmail = data . stateParams . toEmail ;
$scope . description = data . stateParams . description ;
$scope . paypro = data . stateParams . paypro ;
2016-11-25 17:05:35 -03:00
$scope . insufficientFunds = false ;
2016-11-23 11:23:19 -03:00
$scope . noMatchingWallet = false ;
2016-10-20 15:38:57 -03:00
$scope . paymentExpired = {
value : false
} ;
$scope . remainingTimeStr = {
value : null
} ;
2016-09-20 15:28:31 -03:00
var config = configService . getSync ( ) . wallet ;
2016-10-13 10:24:15 -03:00
$scope . feeLevel = config . settings && config . settings . feeLevel ? config . settings . feeLevel : 'normal' ;
2016-12-02 14:48:39 -03:00
if ( $scope . isGlidera ) $scope . network = glideraService . getEnvironment ( ) ;
else $scope . network = ( new bitcore . Address ( $scope . toAddress ) ) . network . name ;
2016-11-29 14:28:43 -03:00
resetValues ( ) ;
2016-11-25 17:05:35 -03:00
setwallets ( ) ;
} ) ;
function setwallets ( ) {
2016-11-23 11:23:19 -03:00
$scope . wallets = profileService . getWallets ( {
2016-09-20 15:28:31 -03:00
onlyComplete : true ,
2016-11-23 11:23:19 -03:00
network : $scope . network ,
2016-11-29 21:49:56 -03:00
n : $scope . isGiftCard ? true : false
2016-09-20 15:28:31 -03:00
} ) ;
2016-11-29 14:28:43 -03:00
if ( ! $scope . wallets || ! $scope . wallets . length ) {
2016-10-10 13:57:25 -03:00
$scope . noMatchingWallet = true ;
2016-11-29 14:28:43 -03:00
if ( $scope . paypro ) {
displayValues ( ) ;
}
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
return ;
}
2016-10-10 13:57:25 -03:00
2016-09-20 15:28:31 -03:00
var filteredWallets = [ ] ;
2016-10-11 10:19:05 -03:00
var index = 0 ;
var enoughFunds = false ;
2016-09-20 15:28:31 -03:00
2016-11-23 11:23:19 -03:00
lodash . each ( $scope . wallets , function ( w ) {
2016-09-20 15:28:31 -03:00
walletService . getStatus ( w , { } , function ( err , status ) {
if ( err || ! status ) {
$log . error ( err ) ;
} else {
2016-10-12 17:40:53 -04:00
w . status = status ;
2016-09-20 15:28:31 -03:00
if ( ! status . availableBalanceSat ) $log . debug ( 'No balance available in: ' + w . name ) ;
2016-11-23 11:23:19 -03:00
if ( status . availableBalanceSat > toAmount ) {
2016-10-10 13:57:25 -03:00
filteredWallets . push ( w ) ;
enoughFunds = true ;
}
2016-09-20 15:28:31 -03:00
}
2016-11-23 11:23:19 -03:00
if ( ++ index == $scope . wallets . length ) {
2016-09-20 15:28:31 -03:00
if ( ! lodash . isEmpty ( filteredWallets ) ) {
$scope . wallets = lodash . clone ( filteredWallets ) ;
2016-12-05 11:11:48 -03:00
if ( $scope . useSendMax ) {
if ( $scope . wallets . length > 1 )
$scope . showWalletSelector ( ) ;
else {
$scope . wallet = $scope . wallets [ 0 ] ;
$scope . getSendMaxInfo ( ) ;
}
} else initConfirm ( ) ;
2016-09-20 15:28:31 -03:00
} else {
2016-11-25 17:05:35 -03:00
if ( ! enoughFunds ) $scope . insufficientFunds = true ;
2016-09-20 15:28:31 -03:00
$log . warn ( 'No wallet available to make the payment' ) ;
}
2016-11-29 11:05:55 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
2016-09-20 15:28:31 -03:00
}
} ) ;
} ) ;
2016-11-25 17:05:35 -03:00
} ;
var initConfirm = function ( ) {
2016-11-23 11:23:19 -03:00
if ( $scope . paypro ) _paymentTimeControl ( $scope . paypro . expires ) ;
2016-10-26 14:00:43 -04:00
2016-11-29 14:28:43 -03:00
displayValues ( ) ;
2016-12-05 11:11:48 -03:00
if ( $scope . wallets . length > 1 ) $scope . showWalletSelector ( ) ;
else $scope . wallet = $scope . wallets [ 0 ] ;
2016-11-29 14:28:43 -03:00
2016-09-22 19:27:59 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
2016-10-26 11:20:57 -03:00
} ) ;
2016-09-20 15:28:31 -03:00
} ;
2016-11-29 14:28:43 -03:00
function displayValues ( ) {
toAmount = parseInt ( toAmount ) ;
$scope . amountStr = txFormatService . formatAmountStr ( toAmount ) ;
$scope . displayAmount = getDisplayAmount ( $scope . amountStr ) ;
$scope . displayUnit = getDisplayUnit ( $scope . amountStr ) ;
txFormatService . formatAlternativeStr ( toAmount , function ( v ) {
$scope . alternativeAmountStr = v ;
} ) ;
2016-12-05 11:54:54 -03:00
if ( $scope . isGlidera == 'buy' ) $scope . getBuyPrice ( ) ;
if ( $scope . isGlidera == 'sell' ) $scope . getSellPrice ( ) ;
2016-11-29 14:28:43 -03:00
} ;
2016-11-29 11:05:55 -03:00
function resetValues ( ) {
$scope . displayAmount = $scope . displayUnit = $scope . fee = $scope . alternativeAmountStr = $scope . insufficientFunds = $scope . noMatchingWallet = null ;
} ;
2016-11-23 11:23:19 -03:00
$scope . getSendMaxInfo = function ( ) {
2016-11-29 11:05:55 -03:00
resetValues ( ) ;
2016-11-25 15:24:02 -03:00
2016-11-23 11:23:19 -03:00
ongoingProcess . set ( 'gettingFeeLevels' , true ) ;
feeService . getCurrentFeeValue ( $scope . network , function ( err , feePerKb ) {
ongoingProcess . set ( 'gettingFeeLevels' , false ) ;
if ( err ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message ) ;
return ;
}
var config = configService . getSync ( ) . wallet ;
ongoingProcess . set ( 'retrievingInputs' , true ) ;
walletService . getSendMaxInfo ( $scope . wallet , {
feePerKb : feePerKb ,
excludeUnconfirmedUtxos : ! config . spendUnconfirmed ,
returnInputs : true ,
} , function ( err , resp ) {
ongoingProcess . set ( 'retrievingInputs' , false ) ;
if ( err ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err ) ;
return ;
}
if ( resp . amount == 0 ) {
2016-11-25 17:05:35 -03:00
$scope . insufficientFunds = true ;
2016-11-23 11:23:19 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , gettextCatalog . getString ( 'Not enough funds for fee' ) ) ;
return ;
}
$scope . sendMaxInfo = {
sendMax : true ,
2016-11-25 15:59:44 -03:00
amount : resp . amount ,
2016-11-23 11:23:19 -03:00
inputs : resp . inputs ,
fee : resp . fee ,
feePerKb : feePerKb ,
} ;
2016-11-24 16:17:01 -03:00
2016-11-25 15:59:44 -03:00
cachedSendMax [ $scope . wallet . id ] = $scope . sendMaxInfo ;
2016-11-29 14:28:43 -03:00
var msg = gettextCatalog . getString ( "{{fee}} will be deducted for bitcoin networking fees." , {
2016-11-29 12:02:10 -03:00
fee : txFormatService . formatAmountStr ( resp . fee )
2016-11-23 11:23:19 -03:00
} ) ;
var warningMsg = verifyExcludedUtxos ( ) ;
if ( ! lodash . isEmpty ( warningMsg ) )
2016-11-29 14:28:43 -03:00
msg += '\n' + warningMsg ;
2016-11-23 11:23:19 -03:00
2016-11-25 10:02:56 -03:00
popupService . showAlert ( null , msg , function ( ) {
2016-11-25 15:59:44 -03:00
setSendMaxValues ( resp ) ;
2016-11-23 11:23:19 -03:00
createTx ( $scope . wallet , true , function ( err , txp ) {
if ( err ) return ;
cachedTxp [ $scope . wallet . id ] = txp ;
apply ( txp ) ;
} ) ;
} ) ;
function verifyExcludedUtxos ( ) {
var warningMsg = [ ] ;
if ( resp . utxosBelowFee > 0 ) {
warningMsg . push ( gettextCatalog . getString ( "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided." , {
2016-11-29 12:02:10 -03:00
amountBelowFeeStr : txFormatService . formatAmountStr ( resp . amountBelowFee )
2016-11-23 11:23:19 -03:00
} ) ) ;
}
if ( resp . utxosAboveMaxSize > 0 ) {
2016-11-29 14:28:43 -03:00
warningMsg . push ( gettextCatalog . getString ( "A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded." , {
2016-11-29 12:02:10 -03:00
amountAboveMaxSizeStr : txFormatService . formatAmountStr ( resp . amountAboveMaxSize )
2016-11-23 11:23:19 -03:00
} ) ) ;
}
return warningMsg . join ( '\n' ) ;
} ;
} ) ;
} ) ;
} ;
2016-11-25 15:59:44 -03:00
function setSendMaxValues ( data ) {
2016-11-29 11:05:55 -03:00
resetValues ( ) ;
2016-11-25 15:59:44 -03:00
var config = configService . getSync ( ) . wallet ;
var unitName = config . settings . unitName ;
var unitToSatoshi = config . settings . unitToSatoshi ;
var satToUnit = 1 / unitToSatoshi ;
var unitDecimals = config . settings . unitDecimals ;
$scope . displayAmount = txFormatService . formatAmount ( data . amount , true ) ;
$scope . displayUnit = unitName ;
2016-11-29 12:02:10 -03:00
$scope . fee = txFormatService . formatAmountStr ( data . fee ) ;
2016-11-25 15:59:44 -03:00
toAmount = parseFloat ( ( data . amount * satToUnit ) . toFixed ( unitDecimals ) ) ;
txFormatService . formatAlternativeStr ( data . amount , function ( v ) {
$scope . alternativeAmountStr = v ;
} ) ;
2016-11-29 11:05:55 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
2016-11-25 15:59:44 -03:00
} ;
2016-09-20 15:28:31 -03:00
$scope . $on ( 'accepted' , function ( event ) {
$scope . approve ( ) ;
} ) ;
2016-09-02 14:55:18 -03:00
2016-10-12 15:01:48 -04:00
$scope . showWalletSelector = function ( ) {
2016-12-05 11:54:54 -03:00
$scope . walletSelectorTitle = $scope . isGlidera == 'buy' ? 'Receive in' : $scope . isGlidera == 'sell' ? 'Sell From' : 'Send from' ;
2016-11-29 11:05:55 -03:00
if ( ! $scope . useSendMax && ( $scope . insufficientFunds || $scope . noMatchingWallet ) ) return ;
2016-10-12 15:01:48 -04:00
$scope . showWallets = true ;
} ;
2016-10-12 20:13:28 -04:00
$scope . onWalletSelect = function ( wallet ) {
2016-11-24 16:38:01 -03:00
if ( $scope . useSendMax ) {
$scope . wallet = wallet ;
2016-11-25 15:59:44 -03:00
if ( cachedSendMax [ wallet . id ] ) {
$log . debug ( 'Send max cached for wallet:' , wallet . id ) ;
setSendMaxValues ( cachedSendMax [ wallet . id ] ) ;
return ;
}
2016-11-24 16:38:01 -03:00
$scope . getSendMaxInfo ( ) ;
} else
setWallet ( wallet ) ;
2016-10-12 18:49:00 -04:00
} ;
2016-08-24 16:53:14 -03:00
$scope . showDescriptionPopup = function ( ) {
2016-09-23 12:07:56 -03:00
var message = gettextCatalog . getString ( 'Add description' ) ;
2016-09-16 21:01:19 -03:00
var opts = {
defaultText : $scope . description
2016-09-07 16:48:16 -03:00
} ;
2016-09-23 12:07:56 -03:00
popupService . showPrompt ( null , message , opts , function ( res ) {
2016-10-11 15:46:02 -03:00
if ( typeof res != 'undefined' ) $scope . description = res ;
2016-09-23 12:07:56 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
2016-11-29 11:05:55 -03:00
} ) ;
2016-08-24 15:47:36 -03:00
} ) ;
} ;
2016-10-12 11:45:11 -04:00
function getDisplayAmount ( amountStr ) {
2016-11-29 14:28:43 -03:00
return $scope . amountStr . split ( ' ' ) [ 0 ] ;
2016-11-23 11:23:19 -03:00
} ;
2016-10-12 11:45:11 -04:00
function getDisplayUnit ( amountStr ) {
2016-11-29 14:28:43 -03:00
return $scope . amountStr . split ( ' ' ) [ 1 ] ;
2016-11-23 11:23:19 -03:00
} ;
2016-10-12 11:45:11 -04:00
2016-10-20 15:38:57 -03:00
function _paymentTimeControl ( expirationTime ) {
$scope . paymentExpired . value = false ;
setExpirationTime ( ) ;
countDown = $interval ( function ( ) {
setExpirationTime ( ) ;
} , 1000 ) ;
function setExpirationTime ( ) {
var now = Math . floor ( Date . now ( ) / 1000 ) ;
if ( now > expirationTime ) {
setExpiredValues ( ) ;
return ;
}
var totalSecs = expirationTime - now ;
var m = Math . floor ( totalSecs / 60 ) ;
var s = totalSecs % 60 ;
$scope . remainingTimeStr . value = ( '0' + m ) . slice ( - 2 ) + ":" + ( '0' + s ) . slice ( - 2 ) ;
2016-11-23 11:23:19 -03:00
} ;
2016-10-20 15:38:57 -03:00
function setExpiredValues ( ) {
$scope . paymentExpired . value = true ;
$scope . remainingTimeStr . value = gettextCatalog . getString ( 'Expired' ) ;
if ( countDown ) $interval . cancel ( countDown ) ;
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
2016-11-23 11:23:19 -03:00
} ;
} ;
2016-10-20 15:38:57 -03:00
2016-08-23 16:15:10 -03:00
function setWallet ( wallet , delayed ) {
2016-08-18 14:51:35 -03:00
var stop ;
2016-08-23 16:15:10 -03:00
$scope . wallet = wallet ;
$scope . fee = $scope . txp = null ;
2016-08-18 11:45:30 -03:00
2016-12-02 14:48:39 -03:00
if ( $scope . isGlidera ) return ;
2016-08-23 16:15:10 -03:00
if ( stop ) {
$timeout . cancel ( stop ) ;
stop = null ;
}
2016-08-18 14:51:35 -03:00
2016-08-23 16:15:10 -03:00
if ( cachedTxp [ wallet . id ] ) {
apply ( cachedTxp [ wallet . id ] ) ;
} else {
stop = $timeout ( function ( ) {
2016-09-02 14:17:47 -03:00
createTx ( wallet , true , function ( err , txp ) {
2016-08-23 16:15:10 -03:00
if ( err ) return ;
cachedTxp [ wallet . id ] = txp ;
apply ( txp ) ;
} ) ;
} , delayed ? 2000 : 1 ) ;
}
2016-11-24 16:26:15 -03:00
$timeout ( function ( ) {
$ionicScrollDelegate . resize ( ) ;
$scope . $apply ( ) ;
2016-11-24 16:38:01 -03:00
} , 10 ) ;
2016-11-23 11:23:19 -03:00
} ;
2016-08-16 18:38:18 -03:00
2016-08-17 15:36:19 -03:00
var setSendError = function ( msg ) {
2016-10-10 15:27:57 -04:00
$scope . sendStatus = '' ;
2016-10-17 14:46:51 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
2016-11-29 11:05:55 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error at confirm' ) , msg ) ;
2016-08-17 13:16:06 -03:00
} ;
2016-08-16 18:38:18 -03:00
2016-08-24 16:53:14 -03:00
function apply ( txp ) {
$scope . fee = txFormatService . formatAmountStr ( txp . fee ) ;
$scope . txp = txp ;
2016-11-24 16:26:15 -03:00
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
2016-11-23 11:23:19 -03:00
} ;
2016-08-24 16:53:14 -03:00
2016-09-02 14:17:47 -03:00
var createTx = function ( wallet , dryRun , cb ) {
2016-08-18 14:51:35 -03:00
var config = configService . getSync ( ) . wallet ;
2016-08-17 13:16:06 -03:00
var currentSpendUnconfirmed = config . spendUnconfirmed ;
var paypro = $scope . paypro ;
2016-08-24 19:12:11 -03:00
var toAddress = $scope . toAddress ;
var description = $scope . description ;
2016-11-23 11:23:19 -03:00
var unitToSatoshi = config . settings . unitToSatoshi ;
var unitDecimals = config . settings . unitDecimals ;
2016-08-16 18:38:18 -03:00
// ToDo: use a credential's (or fc's) function for this
2016-08-24 16:53:14 -03:00
if ( description && ! wallet . credentials . sharedEncryptingKey ) {
2016-08-16 18:38:18 -03:00
var msg = 'Could not add message to imported wallet without shared encrypting key' ;
$log . warn ( msg ) ;
2016-09-01 11:11:40 -03:00
return setSendError ( msg ) ;
2016-08-16 18:38:18 -03:00
}
2016-08-17 13:16:06 -03:00
if ( toAmount > Number . MAX _SAFE _INTEGER ) {
2016-08-16 18:38:18 -03:00
var msg = 'Amount too big' ;
$log . warn ( msg ) ;
2016-09-01 11:11:40 -03:00
return setSendError ( msg ) ;
2016-10-26 14:00:43 -04:00
}
2016-08-16 18:38:18 -03:00
2016-11-23 11:23:19 -03:00
var txp = { } ;
var amount ;
2016-11-29 14:28:43 -03:00
if ( $scope . useSendMax ) amount = parseFloat ( ( toAmount * unitToSatoshi ) . toFixed ( 0 ) ) ;
2016-11-23 11:23:19 -03:00
else amount = toAmount ;
txp . outputs = [ {
2016-08-18 14:51:35 -03:00
'toAddress' : toAddress ,
2016-11-23 11:23:19 -03:00
'amount' : amount ,
2016-08-24 16:53:14 -03:00
'message' : description
2016-11-23 11:23:19 -03:00
} ] ;
2016-08-17 13:16:06 -03:00
2016-11-23 11:23:19 -03:00
if ( $scope . sendMaxInfo ) {
2016-08-18 10:08:23 -03:00
txp . inputs = $scope . sendMaxInfo . inputs ;
2016-11-29 11:05:55 -03:00
txp . fee = $scope . sendMaxInfo . fee ;
2016-11-23 11:23:19 -03:00
} else
txp . feeLevel = config . settings && config . settings . feeLevel ? config . settings . feeLevel : 'normal' ;
2016-08-16 18:38:18 -03:00
2016-08-24 16:53:14 -03:00
txp . message = description ;
2016-11-23 11:23:19 -03:00
if ( paypro ) {
2016-10-26 14:00:43 -04:00
txp . payProUrl = paypro . url ;
}
2016-11-23 11:23:19 -03:00
txp . excludeUnconfirmedUtxos = ! currentSpendUnconfirmed ;
2016-09-02 14:17:47 -03:00
txp . dryRun = dryRun ;
2016-08-16 18:38:18 -03:00
2016-08-18 14:51:35 -03:00
walletService . createTx ( wallet , txp , function ( err , ctxp ) {
2016-08-18 10:08:23 -03:00
if ( err ) {
2016-09-28 17:51:45 -03:00
setSendError ( err ) ;
return cb ( err ) ;
2016-08-18 10:08:23 -03:00
}
2016-08-18 14:51:35 -03:00
return cb ( null , ctxp ) ;
2016-08-17 13:16:06 -03:00
} ) ;
} ;
2016-08-24 19:12:11 -03:00
$scope . openPPModal = function ( ) {
$ionicModal . fromTemplateUrl ( 'views/modals/paypro.html' , {
scope : $scope
} ) . then ( function ( modal ) {
$scope . payproModal = modal ;
$scope . payproModal . show ( ) ;
} ) ;
} ;
2016-10-07 20:12:37 -04:00
$scope . approve = function ( onSendStatusChange ) {
2016-12-05 11:17:48 -03:00
var wallet = $scope . wallet ;
if ( ! wallet ) {
return ;
}
2016-10-26 16:09:21 -04:00
if ( $scope . paypro && $scope . paymentExpired . value ) {
2016-10-27 16:15:11 -04:00
popupService . showAlert ( null , gettextCatalog . getString ( 'This bitcoin payment request has expired.' ) ) ;
2016-10-20 16:44:20 -03:00
$scope . sendStatus = '' ;
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
2016-10-20 15:38:57 -03:00
return ;
}
2016-12-02 14:48:39 -03:00
if ( $scope . isGlidera ) {
$scope . get2faCode ( function ( err , sent ) {
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , gettextCatalog . getString ( 'Could not send confirmation code to your phone' ) ) ;
2016-12-02 14:48:39 -03:00
return ;
}
if ( sent ) {
2016-12-05 12:30:43 -03:00
var title = gettextCatalog . getString ( "Please, enter the code below" ) ;
var message = gettextCatalog . getString ( "A SMS containing a confirmation code was sent to your phone." ) ;
2016-12-02 14:48:39 -03:00
popupService . showPrompt ( title , message , null , function ( twoFaCode ) {
2016-12-05 10:50:54 -03:00
if ( typeof twoFaCode == 'undefined' ) return ;
2016-12-05 15:40:04 -03:00
if ( $scope . isGlidera == 'buy' ) {
2016-12-05 10:27:53 -03:00
$scope . buyRequest ( wallet , twoFaCode , function ( err , data ) {
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err ) ;
2016-12-05 10:27:53 -03:00
return ;
}
$scope . sendStatus = 'success' ;
$timeout ( function ( ) {
$scope . $digest ( ) ;
} ) ;
} )
}
2016-12-05 15:40:04 -03:00
if ( $scope . isGlidera == 'sell' ) {
2016-12-05 10:27:53 -03:00
$scope . sellRequest ( wallet , twoFaCode , function ( err , data ) {
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err ) ;
2016-12-05 10:27:53 -03:00
return ;
}
$scope . sendStatus = 'success' ;
$timeout ( function ( ) {
$scope . $digest ( ) ;
} ) ;
} )
}
2016-12-02 14:48:39 -03:00
} ) ;
}
} ) ;
return ;
}
2016-08-17 13:16:06 -03:00
if ( ! wallet . canSign ( ) && ! wallet . isPrivKeyExternal ( ) ) {
$log . info ( 'No signing proposal: No private key' ) ;
2016-08-18 10:08:23 -03:00
2016-08-18 14:51:35 -03:00
return walletService . onlyPublish ( wallet , txp , function ( err , txp ) {
2016-08-18 10:08:23 -03:00
if ( err ) return setSendError ( err ) ;
2016-08-16 18:38:18 -03:00
} ) ;
2016-08-17 13:16:06 -03:00
}
2016-10-07 20:03:51 -04:00
ongoingProcess . set ( 'creatingTx' , true , onSendStatusChange ) ;
2016-09-02 14:17:47 -03:00
createTx ( wallet , false , function ( err , txp ) {
2016-10-07 20:03:51 -04:00
ongoingProcess . set ( 'creatingTx' , false , onSendStatusChange ) ;
2016-09-02 14:17:47 -03:00
if ( err ) return ;
2016-09-21 11:47:19 -03:00
var config = configService . getSync ( ) ;
var spendingPassEnabled = walletService . isEncrypted ( wallet ) ;
2016-10-12 11:04:05 -03:00
var touchIdEnabled = config . touchIdFor && config . touchIdFor [ wallet . id ] ;
2016-09-21 11:47:19 -03:00
var isCordova = $scope . isCordova ;
var bigAmount = parseFloat ( txFormatService . formatToUSD ( txp . amount ) ) > 20 ;
2016-09-23 10:33:26 -03:00
var message = gettextCatalog . getString ( 'Sending {{amountStr}} from your {{name}} wallet' , {
2016-11-29 14:28:43 -03:00
amountStr : $scope . amountStr ,
2016-09-21 11:47:19 -03:00
name : wallet . name
2016-09-02 14:17:47 -03:00
} ) ;
2016-09-21 11:47:19 -03:00
var okText = gettextCatalog . getString ( 'Confirm' ) ;
var cancelText = gettextCatalog . getString ( 'Cancel' ) ;
if ( ! spendingPassEnabled && ! touchIdEnabled ) {
2016-10-12 10:53:27 -03:00
if ( isCordova ) {
if ( bigAmount ) {
popupService . showConfirm ( null , message , okText , cancelText , function ( ok ) {
if ( ! ok ) {
$scope . sendStatus = '' ;
$timeout ( function ( ) {
$scope . $apply ( ) ;
} ) ;
return ;
}
publishAndSign ( wallet , txp , onSendStatusChange ) ;
} ) ;
2016-10-20 15:38:57 -03:00
} else publishAndSign ( wallet , txp , onSendStatusChange ) ;
} else {
2016-09-21 11:47:19 -03:00
popupService . showConfirm ( null , message , okText , cancelText , function ( ok ) {
2016-10-10 14:33:55 -04:00
if ( ! ok ) {
$scope . sendStatus = '' ;
return ;
}
2016-10-07 20:12:37 -04:00
publishAndSign ( wallet , txp , onSendStatusChange ) ;
2016-09-21 11:47:19 -03:00
} ) ;
}
2016-10-20 15:38:57 -03:00
} else publishAndSign ( wallet , txp , onSendStatusChange ) ;
2016-09-21 11:47:19 -03:00
} ) ;
} ;
2016-10-07 20:12:37 -04:00
function statusChangeHandler ( processName , showName , isOn ) {
2016-10-11 10:19:05 -03:00
$log . debug ( 'statusChangeHandler: ' , processName , showName , isOn ) ;
if ( ( processName === 'broadcastingTx' || ( ( processName === 'signingTx' ) && $scope . wallet . m > 1 ) ) && ! isOn ) {
2016-10-07 20:03:51 -04:00
$scope . sendStatus = 'success' ;
$scope . $digest ( ) ;
2016-10-11 10:19:05 -03:00
} else if ( showName ) {
2016-10-07 20:03:51 -04:00
$scope . sendStatus = showName ;
}
2016-11-23 11:23:19 -03:00
} ;
2016-10-07 20:03:51 -04:00
2016-10-10 15:27:57 -04:00
$scope . statusChangeHandler = statusChangeHandler ;
2016-10-07 20:03:51 -04:00
$scope . onConfirm = function ( ) {
2016-10-07 20:12:37 -04:00
$scope . approve ( statusChangeHandler ) ;
2016-10-07 20:03:51 -04:00
} ;
$scope . onSuccessConfirm = function ( ) {
2016-10-13 17:49:48 -03:00
var previousView = $ionicHistory . viewHistory ( ) . backView && $ionicHistory . viewHistory ( ) . backView . stateName ;
var fromBitPayCard = previousView . match ( /tabs.bitpayCard/ ) ? true : false ;
2016-11-28 17:01:07 -03:00
var fromAmazon = previousView . match ( /tabs.giftcards.amazon/ ) ? true : false ;
2016-12-02 15:40:36 -03:00
var fromGlidera = previousView . match ( /tabs.buyandsell.glidera/ ) ? true : false ;
2016-10-13 17:49:48 -03:00
2016-10-07 20:03:51 -04:00
$ionicHistory . nextViewOptions ( {
disableAnimate : true
} ) ;
2016-10-13 17:49:48 -03:00
$ionicHistory . removeBackView ( ) ;
2016-10-10 15:27:57 -04:00
$scope . sendStatus = '' ;
2016-10-13 17:49:48 -03:00
if ( fromBitPayCard ) {
$timeout ( function ( ) {
2016-10-17 14:46:51 -03:00
$state . transitionTo ( 'tabs.bitpayCard' , {
id : $stateParams . cardId
} ) ;
2016-10-13 17:49:48 -03:00
} , 100 ) ;
2016-11-28 17:01:07 -03:00
} else if ( fromAmazon ) {
$ionicHistory . nextViewOptions ( {
disableAnimate : true ,
historyRoot : true
} ) ;
$ionicHistory . clearHistory ( ) ;
$state . go ( 'tabs.home' ) . then ( function ( ) {
$state . transitionTo ( 'tabs.giftcards.amazon' , {
cardClaimCode : $scope . amazonGiftCard ? $scope . amazonGiftCard . claimCode : null
} ) ;
} ) ;
2016-12-02 15:40:36 -03:00
} else if ( fromGlidera ) {
$ionicHistory . nextViewOptions ( {
disableAnimate : true ,
historyRoot : true
} ) ;
$ionicHistory . clearHistory ( ) ;
$state . go ( 'tabs.home' ) . then ( function ( ) {
$state . transitionTo ( 'tabs.buyandsell.glidera' ) ;
} ) ;
2016-10-13 17:49:48 -03:00
} else {
2016-12-02 17:33:18 -03:00
$ionicHistory . nextViewOptions ( {
disableAnimate : true ,
historyRoot : true
} ) ;
$ionicHistory . clearHistory ( ) ;
$state . go ( 'tabs.send' ) . then ( function ( ) {
$state . transitionTo ( 'tabs.home' ) ;
} ) ;
2016-10-13 17:49:48 -03:00
}
2016-10-07 20:03:51 -04:00
} ;
2016-12-02 14:48:39 -03:00
$scope . get2faCode = function ( cb ) {
2016-12-05 11:17:48 -03:00
ongoingProcess . set ( 'sending2faCode' , true ) ;
2016-12-02 09:48:56 -03:00
$timeout ( function ( ) {
2016-12-02 14:48:39 -03:00
glideraService . get2faCode ( $scope . glideraAccessToken , function ( err , sent ) {
2016-12-05 11:17:48 -03:00
ongoingProcess . set ( 'sending2faCode' , false ) ;
2016-12-02 14:48:39 -03:00
return cb ( err , sent ) ;
} ) ;
} , 100 ) ;
} ;
2016-12-05 10:27:53 -03:00
$scope . buyRequest = function ( wallet , twoFaCode , cb ) {
2016-12-05 11:17:48 -03:00
ongoingProcess . set ( 'buyingBitcoin' , true ) ;
2016-12-02 14:48:39 -03:00
$timeout ( function ( ) {
2016-12-05 10:27:53 -03:00
walletService . getAddress ( wallet , false , function ( err , walletAddr ) {
2016-12-02 09:48:56 -03:00
if ( err ) {
2016-12-05 11:17:48 -03:00
ongoingProcess . set ( 'buyingBitcoin' , false ) ;
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . cb ( err , 'Could not create address' ) ) ;
2016-12-02 09:48:56 -03:00
return ;
}
2016-12-02 14:48:39 -03:00
var data = {
destinationAddress : walletAddr ,
qty : $scope . buyPrice . qty ,
priceUuid : $scope . buyPrice . priceUuid ,
useCurrentPrice : false ,
ip : null
} ;
glideraService . buy ( $scope . glideraAccessToken , twoFaCode , data , function ( err , data ) {
2016-12-05 11:17:48 -03:00
ongoingProcess . set ( 'buyingBitcoin' , false ) ;
2016-12-05 10:27:53 -03:00
return cb ( err , data ) ;
2016-12-02 09:48:56 -03:00
} ) ;
} ) ;
} , 100 ) ;
} ;
2016-12-05 10:27:53 -03:00
$scope . sellRequest = function ( wallet , twoFaCode , cb ) {
var outputs = [ ] ;
var config = configService . getSync ( ) ;
var configWallet = config . wallet ;
var walletSettings = configWallet . settings ;
ongoingProcess . set ( 'creatingTx' , true ) ;
walletService . getAddress ( wallet , null , function ( err , refundAddress ) {
if ( ! refundAddress ) {
ongoingProcess . clear ( ) ;
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err , 'Could not create address' ) ) ;
2016-12-05 10:27:53 -03:00
return ;
}
glideraService . getSellAddress ( $scope . glideraAccessToken , function ( err , sellAddress ) {
if ( ! sellAddress || err ) {
ongoingProcess . clear ( ) ;
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , gettextCatalog . getString ( 'Could not get the destination bitcoin address' ) ) ;
2016-12-05 10:27:53 -03:00
return ;
}
var amount = parseInt ( ( $scope . sellPrice . qty * 100000000 ) . toFixed ( 0 ) ) ;
var comment = 'Glidera transaction' ;
outputs . push ( {
'toAddress' : sellAddress ,
'amount' : amount ,
'message' : comment
} ) ;
var txp = {
toAddress : sellAddress ,
amount : amount ,
outputs : outputs ,
message : comment ,
payProUrl : null ,
excludeUnconfirmedUtxos : configWallet . spendUnconfirmed ? false : true ,
feeLevel : walletSettings . feeLevel || 'normal' ,
customData : {
'glideraToken' : $scope . glideraAccessToken
}
} ;
walletService . createTx ( wallet , txp , function ( err , createdTxp ) {
ongoingProcess . clear ( ) ;
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message || bwcError . msg ( err ) ) ;
2016-12-05 10:27:53 -03:00
return ;
}
walletService . prepare ( wallet , function ( err , password ) {
if ( err ) {
ongoingProcess . clear ( ) ;
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message || bwcError . msg ( err ) ) ;
2016-12-05 10:27:53 -03:00
return ;
}
ongoingProcess . set ( 'signingTx' , true ) ;
walletService . publishTx ( wallet , createdTxp , function ( err , publishedTxp ) {
if ( err ) {
ongoingProcess . clear ( ) ;
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message || bwcError . msg ( err ) ) ;
2016-12-05 10:27:53 -03:00
return ;
}
walletService . signTx ( wallet , publishedTxp , password , function ( err , signedTxp ) {
if ( err ) {
ongoingProcess . clear ( ) ;
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message || bwcError . msg ( err ) ) ;
2016-12-05 10:27:53 -03:00
walletService . removeTx ( wallet , signedTxp , function ( err ) {
if ( err ) $log . debug ( err ) ;
} ) ;
return ;
}
var rawTx = signedTxp . raw ;
var data = {
refundAddress : refundAddress ,
signedTransaction : rawTx ,
priceUuid : $scope . sellPrice . priceUuid ,
useCurrentPrice : $scope . sellPrice . priceUuid ? false : true ,
ip : null
} ;
2016-12-05 11:17:48 -03:00
ongoingProcess . set ( 'sellingBitcoin' , true ) ;
2016-12-05 10:27:53 -03:00
glideraService . sell ( $scope . glideraAccessToken , twoFaCode , data , function ( err , data ) {
ongoingProcess . clear ( ) ;
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message || bwcError . msg ( err ) ) ;
2016-12-05 10:27:53 -03:00
return ;
}
return cb ( err , data )
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
}
2016-12-02 14:48:39 -03:00
$scope . getBuyPrice = function ( ) {
var satToBtc = 1 / 100000000 ;
var price = { } ;
price . qty = ( toAmount * satToBtc ) . toFixed ( 8 ) ;
glideraService . buyPrice ( $scope . glideraAccessToken , price , function ( err , buyPrice ) {
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , 'Could not get exchange information. Please, try again' ) ;
2016-12-02 14:48:39 -03:00
return ;
}
$scope . buyPrice = buyPrice ;
} ) ;
} ;
2016-12-05 10:27:53 -03:00
$scope . getSellPrice = function ( ) {
var satToBtc = 1 / 100000000 ;
var price = { } ;
price . qty = ( toAmount * satToBtc ) . toFixed ( 8 ) ;
glideraService . sellPrice ( $scope . glideraAccessToken , price , function ( err , sellPrice ) {
if ( err ) {
2016-12-05 12:30:43 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , 'Could not get exchange information. Please, try again' ) ;
2016-12-05 10:27:53 -03:00
return ;
}
$scope . sellPrice = sellPrice ;
} ) ;
} ;
2016-10-07 20:12:37 -04:00
function publishAndSign ( wallet , txp , onSendStatusChange ) {
2016-09-21 11:47:19 -03:00
walletService . publishAndSign ( wallet , txp , function ( err , txp ) {
if ( err ) return setSendError ( err ) ;
2016-11-28 17:01:07 -03:00
var previousView = $ionicHistory . viewHistory ( ) . backView && $ionicHistory . viewHistory ( ) . backView . stateName ;
var fromAmazon = previousView . match ( /tabs.giftcards.amazon/ ) ? true : false ;
if ( fromAmazon ) {
var count = 0 ;
var invoiceId = JSON . parse ( $scope . paypro . merchant _data ) . invoiceId ;
var dataSrc = {
currency : 'USD' ,
2016-11-29 21:49:56 -03:00
amount : giftCardAmountUSD ,
uuid : giftCardUUID ,
accessKey : giftCardAccessKey ,
2016-11-28 17:01:07 -03:00
invoiceId : invoiceId ,
invoiceUrl : $scope . paypro . url ,
2016-11-29 21:49:56 -03:00
invoiceTime : giftCardInvoiceTime
2016-11-28 17:01:07 -03:00
} ;
debounceCreate ( count , dataSrc , onSendStatusChange ) ;
}
2016-10-07 20:03:51 -04:00
} , onSendStatusChange ) ;
}
2016-11-28 17:01:07 -03:00
var debounceCreate = lodash . throttle ( function ( count , dataSrc ) {
debounceCreateGiftCard ( count , dataSrc ) ;
} , 8000 , {
'leading' : true
} ) ;
var debounceCreateGiftCard = function ( count , dataSrc , onSendStatusChange ) {
amazonService . createGiftCard ( dataSrc , function ( err , giftCard ) {
$log . debug ( "creating gift card " + count ) ;
if ( err ) {
giftCard = { } ;
giftCard . status = 'FAILURE' ;
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err ) ;
}
if ( giftCard . status == 'PENDING' && count < 3 ) {
$log . debug ( "pending gift card not available yet" ) ;
debounceCreate ( count + 1 , dataSrc ) ;
return ;
}
var now = moment ( ) . unix ( ) * 1000 ;
var newData = giftCard ;
newData [ 'invoiceId' ] = dataSrc . invoiceId ;
newData [ 'accessKey' ] = dataSrc . accessKey ;
newData [ 'invoiceUrl' ] = dataSrc . invoiceUrl ;
newData [ 'amount' ] = dataSrc . amount ;
newData [ 'date' ] = dataSrc . invoiceTime || now ;
newData [ 'uuid' ] = dataSrc . uuid ;
if ( newData . status == 'expired' ) {
amazonService . savePendingGiftCard ( newData , {
remove : true
} , function ( err ) {
$log . error ( err ) ;
return ;
} ) ;
}
amazonService . savePendingGiftCard ( newData , null , function ( err ) {
$log . debug ( "Saving new gift card with status: " + newData . status ) ;
$scope . amazonGiftCard = newData ;
} ) ;
} ) ;
} ;
2016-08-16 18:38:18 -03:00
} ) ;