2016-07-07 16:55:04 -03:00
'use strict' ;
2016-11-03 17:53:32 -03:00
angular . module ( 'copayApp.controllers' ) . controller ( 'amountController' , function ( $rootScope , $scope , $filter , $timeout , $ionicScrollDelegate , gettextCatalog , platformInfo , lodash , configService , rateService , $stateParams , $window , $state , $log , txFormatService , ongoingProcess , bitpayCardService , popupService , bwcError , payproService , amazonService , profileService , bitcore , walletService , feeService ) {
2016-07-09 15:36:49 -03:00
var unitToSatoshi ;
var satToUnit ;
var unitDecimals ;
2016-08-09 15:28:03 -03:00
var satToBtc ;
2016-10-21 03:48:41 -04:00
var SMALL _FONT _SIZE _LIMIT = 10 ;
2016-08-08 16:00:26 -03:00
var LENGTH _EXPRESSION _LIMIT = 19 ;
2016-07-09 15:36:49 -03:00
2016-09-26 18:26:41 -03:00
$scope . $on ( '$ionicView.leave' , function ( ) {
2016-09-23 17:10:34 -03:00
angular . element ( $window ) . off ( 'keydown' ) ;
} ) ;
2016-09-29 10:10:53 -03:00
$scope . $on ( "$ionicView.beforeEnter" , function ( event , data ) {
2016-11-29 21:49:56 -03:00
$scope . isGiftCard = data . stateParams . isGiftCard ;
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 ;
2016-11-29 21:49:56 -03:00
$scope . showAlternativeAmount = ! ! $scope . cardId || ! ! $scope . isGiftCard ;
2016-10-13 17:11:19 -03:00
$scope . toColor = data . stateParams . toColor ;
2016-11-03 18:27:59 -03:00
$scope . network = ( new bitcore . Address ( $scope . toAddress ) ) . network . name ;
2016-11-03 17:53:32 -03:00
$scope . wallets = profileService . getWallets ( {
2016-11-03 18:27:59 -03:00
network : $scope . network
2016-11-03 17:53:32 -03:00
} ) ;
2016-09-28 17:51:45 -03:00
2016-11-24 11:42:25 -03:00
$scope . customAmount = data . stateParams . customAmount ;
2016-11-29 21:49:56 -03:00
if ( ! $scope . cardId && ! $scope . isGiftCard && ! data . stateParams . toAddress ) {
2016-08-16 18:38:18 -03:00
$log . error ( 'Bad params at amount' )
throw ( 'bad params' ) ;
}
var reNr = /^[1234567890\.]$/ ;
var reOp = /^[\*\+\-\/]$/ ;
var disableKeys = angular . element ( $window ) . on ( 'keydown' , function ( e ) {
if ( e . which === 8 ) { // you can add others here inside brackets.
e . preventDefault ( ) ;
$scope . removeDigit ( ) ;
}
if ( e . key && e . key . match ( reNr ) )
$scope . pushDigit ( e . key ) ;
else if ( e . key && e . key . match ( reOp ) )
$scope . pushOperator ( e . key ) ;
else if ( e . key && e . key == 'Enter' )
$scope . finish ( ) ;
$timeout ( function ( ) {
$scope . $apply ( ) ;
} , 10 ) ;
} ) ;
2016-07-07 16:55:04 -03:00
var config = configService . getSync ( ) . wallet . settings ;
$scope . unitName = config . unitName ;
$scope . alternativeIsoCode = config . alternativeIsoCode ;
2016-08-01 17:09:03 -03:00
$scope . specificAmount = $scope . specificAlternativeAmount = '' ;
2016-07-19 17:10:40 -03:00
$scope . isCordova = platformInfo . isCordova ;
2016-07-09 15:36:49 -03:00
unitToSatoshi = config . unitToSatoshi ;
satToUnit = 1 / unitToSatoshi ;
2016-08-09 15:28:03 -03:00
satToBtc = 1 / 100000000 ;
2016-07-09 15:36:49 -03:00
unitDecimals = config . unitDecimals ;
2016-08-16 18:38:18 -03:00
2016-09-27 16:01:15 -03:00
$scope . resetAmount ( ) ;
2016-08-16 18:38:18 -03:00
// in SAT ALWAYS
if ( $stateParams . toAmount ) {
2016-08-30 12:52:28 -03:00
$scope . amount = ( ( $stateParams . toAmount ) * satToUnit ) . toFixed ( unitDecimals ) ;
2016-08-16 18:38:18 -03:00
}
2016-08-10 12:08:39 -03:00
processAmount ( $scope . amount ) ;
2016-08-16 18:38:18 -03:00
2016-08-05 15:44:30 -03:00
$timeout ( function ( ) {
$ionicScrollDelegate . resize ( ) ;
2016-09-28 15:45:21 -03:00
} , 10 ) ;
2016-09-22 10:34:00 -03:00
} ) ;
2016-07-07 16:55:04 -03:00
2016-11-03 17:53:32 -03:00
$scope . getSendMaxInfo = function ( wallet ) {
2016-11-08 11:27:47 -03:00
ongoingProcess . set ( 'gettingFeeLevels' , true ) ;
2016-11-03 18:27:59 -03:00
feeService . getCurrentFeeValue ( $scope . network , function ( err , fee ) {
2016-11-08 11:27:47 -03:00
ongoingProcess . set ( 'gettingFeeLevels' , false ) ;
2016-11-03 17:53:32 -03:00
if ( err ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err . message ) ;
return ;
}
2016-11-08 11:27:47 -03:00
2016-11-03 17:53:32 -03:00
var config = configService . getSync ( ) ;
ongoingProcess . set ( 'retrivingInputs' , true ) ;
walletService . getSendMaxInfo ( wallet , {
2016-11-08 11:27:47 -03:00
feePerKb : fee ,
2016-11-03 17:53:32 -03:00
excludeUnconfirmedUtxos : ! config . wallet . spendUnconfirmed ,
returnInputs : true ,
} , function ( err , resp ) {
ongoingProcess . set ( 'retrivingInputs' , false ) ;
if ( err ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , err ) ;
return ;
}
if ( resp . amount == 0 ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , gettextCatalog . getString ( 'Not enough funds for fee' ) ) ;
return ;
}
2016-11-08 11:27:47 -03:00
var msg = gettextCatalog . getString ( "{{fee}} will be deducted for bitcoin networking fees" , {
fee : txFormatService . formatAmount ( resp . fee ) + ' ' + $scope . unitName
} ) ;
var warningMsg = verifyExcludedUtxos ( ) ;
if ( ! lodash . isEmpty ( warningMsg ) )
msg += '. \n' + warningMsg ;
popupService . showConfirm ( null , msg , 'Ok' , gettextCatalog . getString ( 'Cancel' ) , function ( result ) {
if ( ! result ) return ;
var amount = ( resp . amount * satToUnit ) . toFixed ( 0 ) ;
$scope . amount = amount ;
processAmount ( amount ) ;
} ) ;
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." , {
amountBelowFeeStr : txFormatService . formatAmount ( resp . amountBelowFee ) + ' ' + $scope . unitName
} ) ) ;
}
if ( resp . utxosAboveMaxSize > 0 ) {
warningMsg . push ( gettextCatalog . getString ( "A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded" , {
amountAboveMaxSizeStr : txFormatService . formatAmount ( resp . amountAboveMaxSize ) + ' ' + $scope . unitName
} ) ) ;
}
return warningMsg . join ( '\n' ) ;
} ;
2016-11-03 17:53:32 -03:00
} ) ;
} ) ;
} ;
$scope . showWalletSelector = function ( ) {
$scope . showWallets = true ;
} ;
2016-07-09 15:36:49 -03:00
$scope . toggleAlternative = function ( ) {
2016-07-18 14:50:39 -03:00
$scope . showAlternativeAmount = ! $scope . showAlternativeAmount ;
2016-08-01 18:28:39 -03:00
2016-08-02 12:44:47 -03:00
if ( $scope . amount && isExpression ( $scope . amount ) ) {
var amount = evaluate ( format ( $scope . amount ) ) ;
2016-08-08 16:00:26 -03:00
$scope . globalResult = '= ' + processResult ( amount ) ;
2016-08-01 18:28:39 -03:00
}
2016-07-09 15:36:49 -03:00
} ;
2016-07-07 16:55:04 -03:00
2016-08-01 17:35:31 -03:00
function checkFontSize ( ) {
2016-08-08 16:00:26 -03:00
if ( $scope . amount && $scope . amount . length >= SMALL _FONT _SIZE _LIMIT ) $scope . smallFont = true ;
2016-08-01 17:35:31 -03:00
else $scope . smallFont = false ;
} ;
2016-07-09 15:36:49 -03:00
$scope . pushDigit = function ( digit ) {
2016-08-08 16:00:26 -03:00
if ( $scope . amount && $scope . amount . length >= LENGTH _EXPRESSION _LIMIT ) return ;
2016-10-10 12:08:21 -04:00
if ( $scope . amount . indexOf ( '.' ) > - 1 && digit == '.' ) return ;
2016-10-13 17:11:19 -03:00
if ( $scope . showAlternativeAmount && $scope . amount . indexOf ( '.' ) > - 1 && $scope . amount [ $scope . amount . indexOf ( '.' ) + 2 ] ) return ;
2016-07-09 15:36:49 -03:00
2016-08-02 12:44:47 -03:00
$scope . amount = ( $scope . amount + digit ) . replace ( '..' , '.' ) ;
2016-08-08 16:00:26 -03:00
checkFontSize ( ) ;
2016-08-01 17:09:03 -03:00
processAmount ( $scope . amount ) ;
2016-07-09 15:36:49 -03:00
} ;
2016-07-07 16:55:04 -03:00
2016-07-09 15:36:49 -03:00
$scope . pushOperator = function ( operator ) {
2016-08-01 17:09:03 -03:00
if ( ! $scope . amount || $scope . amount . length == 0 ) return ;
$scope . amount = _pushOperator ( $scope . amount ) ;
2016-07-07 16:55:04 -03:00
2016-07-09 15:36:49 -03:00
function _pushOperator ( val ) {
if ( ! isOperator ( lodash . last ( val ) ) ) {
return val + operator ;
} else {
return val . slice ( 0 , - 1 ) + operator ;
2016-07-07 16:55:04 -03:00
}
} ;
2016-07-09 15:36:49 -03:00
} ;
2016-07-07 16:55:04 -03:00
2016-07-09 15:36:49 -03:00
function isOperator ( val ) {
2016-07-15 15:36:00 -03:00
var regex = /[\/\-\+\x\*]/ ;
2016-08-08 16:00:26 -03:00
return regex . test ( val ) ;
2016-07-09 15:36:49 -03:00
} ;
2016-07-07 16:55:04 -03:00
2016-08-01 17:09:03 -03:00
function isExpression ( val ) {
2016-08-02 12:44:47 -03:00
var regex = /^\.?\d+(\.?\d+)?([\/\-\+\*x]\d?\.?\d+)+$/ ;
2016-08-08 16:00:26 -03:00
return regex . test ( val ) ;
2016-08-01 17:09:03 -03:00
} ;
$scope . removeDigit = function ( ) {
$scope . amount = $scope . amount . slice ( 0 , - 1 ) ;
processAmount ( $scope . amount ) ;
2016-08-01 17:35:31 -03:00
checkFontSize ( ) ;
2016-07-09 15:36:49 -03:00
} ;
2016-08-05 15:26:27 -03:00
$scope . resetAmount = function ( ) {
2016-08-01 17:09:03 -03:00
$scope . amount = $scope . alternativeResult = $scope . amountResult = $scope . globalResult = '' ;
2016-10-21 15:12:03 -03:00
$scope . allowSend = false ;
2016-08-01 17:35:31 -03:00
checkFontSize ( ) ;
2016-07-09 15:36:49 -03:00
} ;
function processAmount ( val ) {
if ( ! val ) {
2016-08-05 15:26:27 -03:00
$scope . resetAmount ( ) ;
2016-07-09 15:36:49 -03:00
return ;
}
2016-07-19 12:00:58 -03:00
var formatedValue = format ( val ) ;
2016-07-15 15:36:00 -03:00
var result = evaluate ( formatedValue ) ;
2016-10-21 15:12:03 -03:00
$scope . allowSend = lodash . isNumber ( result ) && + result > 0 ;
2016-07-09 15:36:49 -03:00
if ( lodash . isNumber ( result ) ) {
2016-08-08 16:00:26 -03:00
$scope . globalResult = isExpression ( val ) ? '= ' + processResult ( result ) : '' ;
2016-08-01 18:28:39 -03:00
$scope . amountResult = $filter ( 'formatFiatAmount' ) ( toFiat ( result ) ) ;
2016-08-18 11:45:30 -03:00
$scope . alternativeResult = txFormatService . formatAmount ( fromFiat ( result ) * unitToSatoshi , true ) ;
2016-07-09 15:36:49 -03:00
}
} ;
2016-08-08 16:00:26 -03:00
function processResult ( val ) {
if ( $scope . showAlternativeAmount )
return $filter ( 'formatFiatAmount' ) ( val ) ;
else
2016-08-18 11:45:30 -03:00
return txFormatService . formatAmount ( val . toFixed ( unitDecimals ) * unitToSatoshi , true ) ;
2016-08-08 16:00:26 -03:00
} ;
2016-07-19 12:00:58 -03:00
function fromFiat ( val ) {
return parseFloat ( ( rateService . fromFiat ( val , $scope . alternativeIsoCode ) * satToUnit ) . toFixed ( unitDecimals ) , 10 ) ;
} ;
function toFiat ( val ) {
return parseFloat ( ( rateService . toFiat ( val * unitToSatoshi , $scope . alternativeIsoCode ) ) . toFixed ( 2 ) , 10 ) ;
} ;
2016-07-09 15:36:49 -03:00
function evaluate ( val ) {
var result ;
try {
2016-07-20 16:16:39 -03:00
result = $scope . $eval ( val ) ;
2016-07-09 15:36:49 -03:00
} catch ( e ) {
2016-08-01 17:09:03 -03:00
return 0 ;
2016-07-09 15:36:49 -03:00
}
2016-08-08 16:00:26 -03:00
if ( ! lodash . isFinite ( result ) ) return 0 ;
2016-07-09 15:36:49 -03:00
return result ;
} ;
2016-07-19 12:00:58 -03:00
function format ( val ) {
2016-07-20 16:26:15 -03:00
var result = val . toString ( ) ;
if ( isOperator ( lodash . last ( val ) ) )
result = result . slice ( 0 , - 1 ) ;
return result . replace ( 'x' , '*' ) ;
2016-07-15 15:36:00 -03:00
} ;
2016-07-19 12:00:58 -03:00
$scope . finish = function ( ) {
2016-08-10 14:27:46 -03:00
var _amount = evaluate ( format ( $scope . amount ) ) ;
2016-09-28 17:51:45 -03:00
2016-10-06 19:23:39 -03:00
if ( $scope . cardId ) {
2016-09-28 17:51:45 -03:00
var amountUSD = $scope . showAlternativeAmount ? _amount : $filter ( 'formatFiatAmount' ) ( toFiat ( _amount ) ) ;
var dataSrc = {
amount : amountUSD ,
currency : 'USD'
} ;
2016-11-28 17:01:07 -03:00
2016-10-21 03:48:41 -04:00
ongoingProcess . set ( 'Preparing transaction...' , true ) ;
2016-09-28 17:51:45 -03:00
$timeout ( function ( ) {
2016-10-06 19:23:39 -03:00
bitpayCardService . topUp ( $scope . cardId , dataSrc , function ( err , invoiceId ) {
2016-09-28 17:51:45 -03:00
if ( err ) {
2016-10-21 03:48:41 -04:00
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
2016-09-28 17:51:45 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err ) ) ;
return ;
}
bitpayCardService . getInvoice ( invoiceId , function ( err , data ) {
if ( err ) {
2016-10-26 16:03:20 -04:00
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
2016-09-28 17:51:45 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err ) ) ;
return ;
}
var payProUrl = data . paymentUrls . BIP73 ;
2016-10-26 16:03:20 -04:00
payproService . getPayProDetails ( payProUrl , function ( err , payProDetails ) {
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
if ( err ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err ) ) ;
return ;
}
var stateParams = {
cardId : $scope . cardId ,
toName : $scope . toName ,
toAmount : payProDetails . amount ,
toAddress : payProDetails . toAddress ,
description : payProDetails . memo ,
paypro : payProDetails
} ;
$state . transitionTo ( 'tabs.bitpayCard.confirm' , stateParams ) ;
} , true ) ;
2016-09-28 17:51:45 -03:00
} ) ;
} ) ;
} ) ;
2016-11-29 21:49:56 -03:00
} else if ( $scope . isGiftCard ) {
2016-11-28 17:01:07 -03:00
ongoingProcess . set ( 'Preparing transaction...' , true ) ;
2016-11-29 10:50:48 -03:00
// Get first wallet as UUID
var uuid ;
try {
uuid = profileService . getWallets ( {
onlyComplete : true ,
network : 'livenet' ,
} ) [ 0 ] . id ;
2016-11-03 17:53:32 -03:00
} catch ( err ) {
2016-12-01 12:09:43 -03:00
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
2016-11-29 10:50:48 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , gettextCatalog . getString ( 'No wallet found!' ) ) ;
return ;
} ;
2016-11-28 17:01:07 -03:00
var amountUSD = $scope . showAlternativeAmount ? _amount : $filter ( 'formatFiatAmount' ) ( toFiat ( _amount ) ) ;
var dataSrc = {
currency : 'USD' ,
amount : amountUSD ,
2016-11-29 10:50:48 -03:00
uuid : uuid
2016-11-28 17:01:07 -03:00
} ;
amazonService . createBitPayInvoice ( dataSrc , function ( err , dataInvoice ) {
if ( err ) {
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err ) ) ;
return ;
}
amazonService . getBitPayInvoice ( dataInvoice . invoiceId , function ( err , invoice ) {
if ( err ) {
2016-12-01 12:09:43 -03:00
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
2016-11-28 17:01:07 -03:00
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err ) ) ;
return ;
}
var payProUrl = invoice . paymentUrls . BIP73 ;
payproService . getPayProDetails ( payProUrl , function ( err , payProDetails ) {
ongoingProcess . set ( 'Preparing transaction...' , false ) ;
if ( err ) {
popupService . showAlert ( gettextCatalog . getString ( 'Error' ) , bwcError . msg ( err ) ) ;
return ;
}
var stateParams = {
2016-11-29 21:49:56 -03:00
giftCardAmountUSD : amountUSD ,
giftCardAccessKey : dataInvoice . accessKey ,
giftCardInvoiceTime : invoice . invoiceTime ,
giftCardUUID : dataSrc . uuid ,
2016-11-28 17:01:07 -03:00
toAmount : payProDetails . amount ,
toAddress : payProDetails . toAddress ,
description : payProDetails . memo ,
paypro : payProDetails
} ;
$state . transitionTo ( 'tabs.giftcards.amazon.confirm' , stateParams ) ;
} , true ) ;
} ) ;
} ) ;
2016-09-28 17:51:45 -03:00
} else {
2016-11-01 12:03:24 -03:00
var amount = $scope . showAlternativeAmount ? fromFiat ( _amount ) : _amount ;
2016-11-24 11:42:25 -03:00
if ( $scope . customAmount ) {
$state . transitionTo ( 'tabs.receive.customAmount' , {
toAmount : ( amount * unitToSatoshi ) . toFixed ( 0 ) ,
toAddress : $scope . toAddress
} ) ;
} else {
$state . transitionTo ( 'tabs.send.confirm' , {
isWallet : $scope . isWallet ,
toAmount : ( amount * unitToSatoshi ) . toFixed ( 0 ) ,
toAddress : $scope . toAddress ,
toName : $scope . toName ,
toEmail : $scope . toEmail
} ) ;
}
2016-09-28 17:51:45 -03:00
}
2016-07-18 14:50:39 -03:00
} ;
2016-07-09 15:36:49 -03:00
} ) ;