2014-04-17 07:46:49 -07:00
'use strict' ;
2014-06-12 13:42:26 -07:00
var bitcore = require ( 'bitcore' ) ;
2014-04-17 07:46:49 -07:00
2014-06-03 13:42:36 -07:00
angular . module ( 'copayApp.services' )
2014-08-12 12:26:15 -07:00
. factory ( 'controllerUtils' , function ( $rootScope , $sce , $location , notification , $timeout , Socket , video , uriHandler ) {
var root = { } ;
root . getVideoMutedStatus = function ( copayer ) {
if ( ! $rootScope . videoInfo ) return ;
var vi = $rootScope . videoInfo [ copayer ]
if ( ! vi ) {
return ;
}
return vi . muted ;
} ;
2014-07-07 15:38:45 -07:00
2014-08-12 12:26:15 -07:00
root . redirIfLogged = function ( ) {
if ( $rootScope . wallet ) {
$rootScope . wallet . path ( 'receive' ) ;
}
} ;
2014-05-07 15:04:36 -07:00
2014-08-12 12:26:15 -07:00
root . logout = function ( ) {
if ( $rootScope . wallet )
$rootScope . wallet . disconnect ( ) ;
2014-08-06 14:41:37 -07:00
2014-08-12 12:26:15 -07:00
Socket . removeAllListeners ( ) ;
2014-06-24 08:57:15 -07:00
2014-08-15 09:43:43 -07:00
$rootScope . wallet = null ;
2014-08-12 12:26:15 -07:00
delete $rootScope [ 'wallet' ] ;
2014-05-16 14:33:06 -07:00
2014-08-12 12:26:15 -07:00
video . close ( ) ;
// Clear rootScope
for ( var i in $rootScope ) {
if ( i . charAt ( 0 ) != '$' ) {
delete $rootScope [ i ] ;
}
2014-04-23 17:20:44 -07:00
}
2014-04-23 14:07:20 -07:00
2014-08-12 12:26:15 -07:00
$location . path ( '/' ) ;
} ;
2014-06-12 07:03:24 -07:00
2014-08-12 12:26:15 -07:00
root . onError = function ( scope ) {
if ( scope ) scope . loading = false ;
root . logout ( ) ;
}
2014-06-12 07:03:24 -07:00
2014-08-12 12:26:15 -07:00
root . onErrorDigest = function ( scope , msg ) {
root . onError ( scope ) ;
if ( msg ) {
notification . error ( 'Error' , msg ) ;
}
$rootScope . $digest ( ) ;
} ;
root . installStartupHandlers = function ( wallet , $scope ) {
wallet . on ( 'connectionError' , function ( ) {
var message = "Looks like you are already connected to this wallet, please logout and try importing it again." ;
notification . error ( 'PeerJS Error' , message ) ;
root . onErrorDigest ( $scope ) ;
} ) ;
wallet . on ( 'serverError' , function ( m ) {
var message = m || 'The PeerJS server is not responding, please try again' ;
$location . path ( 'receive' ) ;
root . onErrorDigest ( $scope , message ) ;
} ) ;
wallet . on ( 'ready' , function ( ) {
$scope . loading = false ;
} ) ;
} ;
root . setupRootVariables = function ( ) {
uriHandler . register ( ) ;
$rootScope . unitName = config . unitName ;
$rootScope . txAlertCount = 0 ;
$rootScope . insightError = 0 ;
$rootScope . isCollapsed = true ;
$rootScope . $watch ( 'txAlertCount' , function ( txAlertCount ) {
if ( txAlertCount && txAlertCount > 0 ) {
notification . info ( 'New Transaction' , ( $rootScope . txAlertCount == 1 ) ? 'You have a pending transaction proposal' : 'You have ' + $rootScope . txAlertCount + ' pending transaction proposals' , txAlertCount ) ;
}
} ) ;
2014-07-08 04:58:24 -07:00
2014-08-12 12:26:15 -07:00
$rootScope . $watch ( 'receivedFund' , function ( receivedFund ) {
if ( receivedFund ) {
var currentAddr ;
for ( var i = 0 ; i < $rootScope . addrInfos . length ; i ++ ) {
var addrinfo = $rootScope . addrInfos [ i ] ;
if ( addrinfo . address . toString ( ) == receivedFund [ 1 ] && ! addrinfo . isChange ) {
currentAddr = addrinfo . address . toString ( ) ;
break ;
2014-07-08 04:58:24 -07:00
}
}
2014-08-12 12:26:15 -07:00
if ( currentAddr ) {
//var beep = new Audio('sound/transaction.mp3');
notification . funds ( 'Received fund' , currentAddr , receivedFund ) ;
//beep.play();
}
}
} ) ;
2014-07-08 04:58:24 -07:00
2014-08-12 12:26:15 -07:00
} ;
2014-06-24 08:57:15 -07:00
2014-06-12 07:03:24 -07:00
2014-08-12 12:26:15 -07:00
root . startNetwork = function ( w , $scope ) {
Socket . removeAllListeners ( ) ;
2014-06-12 07:03:24 -07:00
2014-08-12 12:26:15 -07:00
root . setupRootVariables ( ) ;
root . installStartupHandlers ( w , $scope ) ;
root . setSocketHandlers ( ) ;
2014-04-24 19:13:55 -07:00
2014-08-12 12:26:15 -07:00
var handlePeerVideo = function ( err , peerID , url ) {
if ( err ) {
delete $rootScope . videoInfo [ peerID ] ;
return ;
}
$rootScope . videoInfo [ peerID ] = {
url : encodeURI ( url ) ,
muted : peerID === w . network . peerId
2014-04-23 17:20:44 -07:00
} ;
2014-08-12 12:26:15 -07:00
$rootScope . $digest ( ) ;
} ;
2014-05-20 07:05:18 -07:00
2014-08-12 12:26:15 -07:00
notification . enableHtml5Mode ( ) ; // for chrome: if support, enable it
2014-05-20 07:05:18 -07:00
2014-08-12 12:26:15 -07:00
w . on ( 'badMessage' , function ( peerId ) {
notification . error ( 'Error' , 'Received wrong message from peer ' + peerId ) ;
} ) ;
w . on ( 'ready' , function ( myPeerID ) {
$rootScope . wallet = w ;
if ( $rootScope . pendingPayment ) {
$location . path ( 'send' ) ;
} else {
$location . path ( 'receive' ) ;
}
if ( ! config . disableVideo )
video . setOwnPeer ( myPeerID , w , handlePeerVideo ) ;
} ) ;
2014-05-16 14:48:17 -07:00
2014-08-12 12:26:15 -07:00
w . on ( 'publicKeyRingUpdated' , function ( dontDigest ) {
root . setSocketHandlers ( ) ;
if ( ! dontDigest ) {
2014-05-09 07:59:38 -07:00
$rootScope . $digest ( ) ;
2014-08-12 12:26:15 -07:00
}
} ) ;
w . on ( 'txProposalsUpdated' , function ( dontDigest ) {
root . updateTxs ( ) ;
// give sometime to the tx to propagate.
$timeout ( function ( ) {
root . updateBalance ( function ( ) {
if ( ! dontDigest ) {
$rootScope . $digest ( ) ;
}
} ) ;
} , 3000 ) ;
} ) ;
w . on ( 'txProposalEvent' , function ( e ) {
var user = w . publicKeyRing . nicknameForCopayer ( e . cId ) ;
switch ( e . type ) {
case 'signed' :
notification . info ( 'Transaction Update' , 'A transaction was signed by ' + user ) ;
break ;
case 'rejected' :
notification . info ( 'Transaction Update' , 'A transaction was rejected by ' + user ) ;
break ;
case 'corrupt' :
notification . error ( 'Transaction Error' , 'Received corrupt transaction from ' + user ) ;
break ;
}
} ) ;
w . on ( 'addressBookUpdated' , function ( dontDigest ) {
if ( ! dontDigest ) {
2014-05-09 10:44:05 -07:00
$rootScope . $digest ( ) ;
2014-08-12 12:26:15 -07:00
}
} ) ;
w . on ( 'connectionError' , function ( msg ) {
root . onErrorDigest ( null , msg ) ;
} ) ;
w . on ( 'connect' , function ( peerID ) {
if ( peerID && ! config . disableVideo ) {
video . callPeer ( peerID , handlePeerVideo ) ;
}
$rootScope . $digest ( ) ;
} ) ;
w . on ( 'disconnect' , function ( peerID ) {
$rootScope . $digest ( ) ;
} ) ;
w . on ( 'close' , root . onErrorDigest ) ;
2014-08-15 09:43:43 -07:00
w . on ( 'locked' , root . onErrorDigest . bind ( this ) ) ;
2014-08-12 12:26:15 -07:00
w . netStart ( ) ;
} ;
root . updateAddressList = function ( ) {
var w = $rootScope . wallet ;
if ( w && w . isReady ( ) )
$rootScope . addrInfos = w . getAddressesInfo ( ) ;
} ;
root . updateBalance = function ( cb ) {
var w = $rootScope . wallet ;
if ( ! w ) return root . onErrorDigest ( ) ;
if ( ! w . isReady ( ) ) return ;
$rootScope . balanceByAddr = { } ;
$rootScope . updatingBalance = true ;
w . getBalance ( function ( err , balanceSat , balanceByAddrSat , safeBalanceSat ) {
if ( err ) {
console . error ( 'Error: ' + err . message ) ; //TODO
root . _setCommError ( ) ;
return null ;
} else {
root . _clearCommError ( ) ;
}
2014-06-16 08:44:18 -07:00
var satToUnit = 1 / config . unitToSatoshi ;
2014-08-12 12:26:15 -07:00
var COIN = bitcore . util . COIN ;
2014-05-13 00:03:09 -07:00
2014-08-12 12:26:15 -07:00
$rootScope . totalBalance = balanceSat * satToUnit ;
$rootScope . totalBalanceBTC = ( balanceSat / COIN ) ;
$rootScope . availableBalance = safeBalanceSat * satToUnit ;
$rootScope . availableBalanceBTC = ( safeBalanceSat / COIN ) ;
2014-05-20 14:34:55 -07:00
2014-08-12 12:26:15 -07:00
$rootScope . lockedBalance = ( balanceSat - safeBalanceSat ) * satToUnit ;
$rootScope . lockedBalanceBTC = ( balanceSat - safeBalanceSat ) / COIN ;
2014-08-06 09:59:33 -07:00
2014-08-12 12:26:15 -07:00
var balanceByAddr = { } ;
for ( var ii in balanceByAddrSat ) {
balanceByAddr [ ii ] = balanceByAddrSat [ ii ] * satToUnit ;
}
$rootScope . balanceByAddr = balanceByAddr ;
root . updateAddressList ( ) ;
$rootScope . updatingBalance = false ;
return cb ? cb ( ) : null ;
} ) ;
} ;
root . updateTxs = function ( opts ) {
var w = $rootScope . wallet ;
if ( ! w ) return ;
opts = opts || $rootScope . txsOpts || { } ;
var satToUnit = 1 / config . unitToSatoshi ;
var myCopayerId = w . getMyCopayerId ( ) ;
var pendingForUs = 0 ;
var inT = w . getTxProposals ( ) . sort ( function ( t1 , t2 ) {
return t2 . createdTs - t1 . createdTs
} ) ;
var txs = [ ] ;
2014-06-16 08:44:18 -07:00
2014-08-12 12:26:15 -07:00
inT . forEach ( function ( i , index ) {
if ( opts . skip && ( index < opts . skip [ 0 ] || index >= opts . skip [ 1 ] ) ) {
return txs . push ( null ) ;
2014-05-13 01:02:21 -07:00
}
2014-05-13 00:03:09 -07:00
2014-08-12 12:26:15 -07:00
if ( myCopayerId != i . creator && ! i . finallyRejected && ! i . sentTs && ! i . rejectedByUs && ! i . signedByUs ) {
pendingForUs ++ ;
}
if ( ! i . finallyRejected && ! i . sentTs ) {
i . isPending = 1 ;
}
2014-08-04 09:54:08 -07:00
2014-08-12 12:26:15 -07:00
if ( ! ! opts . pending == ! ! i . isPending ) {
var tx = i . builder . build ( ) ;
var outs = [ ] ;
tx . outs . forEach ( function ( o ) {
var addr = bitcore . Address . fromScriptPubKey ( o . getScript ( ) , config . networkName ) [ 0 ] . toString ( ) ;
if ( ! w . addressIsOwn ( addr , {
excludeMain : true
} ) ) {
outs . push ( {
address : addr ,
value : bitcore . util . valueToBigInt ( o . getValue ( ) ) * satToUnit ,
} ) ;
}
} ) ;
// extra fields
i . outs = outs ;
i . fee = i . builder . feeSat * satToUnit ;
i . missingSignatures = tx . countInputMissingSignatures ( 0 ) ;
i . actionList = getActionList ( i . peerActions ) ;
txs . push ( i ) ;
}
} ) ;
$rootScope . txs = txs ;
$rootScope . txsOpts = opts ;
if ( $rootScope . pendingTxCount < pendingForUs ) {
$rootScope . txAlertCount = pendingForUs ;
2014-08-04 09:54:08 -07:00
}
2014-08-12 12:26:15 -07:00
$rootScope . pendingTxCount = pendingForUs ;
} ;
2014-08-04 09:54:08 -07:00
2014-08-12 12:26:15 -07:00
function getActionList ( actions ) {
var peers = Object . keys ( actions ) . map ( function ( i ) {
return { cId : i , actions : actions [ i ] }
2014-06-30 08:00:14 -07:00
} ) ;
2014-08-12 12:26:15 -07:00
return peers . sort ( function ( a , b ) {
return ! ! b . actions . create - ! ! a . actions . create ;
} ) ;
}
2014-08-14 06:23:37 -07:00
var connectionLost = false ;
2014-08-12 12:26:15 -07:00
$rootScope . $watch ( 'insightError' , function ( status ) {
2014-08-14 06:23:37 -07:00
if ( ! status ) return ;
// Reconnected
if ( status === - 1 ) {
if ( ! connectionLost ) return ; // Skip on first reconnect
connectionLost = false ;
notification . success ( 'Networking restored' , 'Connection to Insight re-established' ) ;
return ;
2014-08-12 12:26:15 -07:00
}
2014-08-14 06:23:37 -07:00
// Retry
if ( status == 1 ) return ; // Skip the first try
connectionLost = true ;
notification . error ( 'Networking problem' , 'Connection to Insight lost, reconnecting (attempt number ' + ( status - 1 ) + ')' ) ;
2014-08-12 12:26:15 -07:00
} ) ;
2014-06-04 14:10:47 -07:00
2014-08-12 12:26:15 -07:00
root . _setCommError = function ( e ) {
if ( $rootScope . insightError < 0 )
$rootScope . insightError = 0 ;
$rootScope . insightError ++ ;
} ;
2014-06-04 14:10:47 -07:00
2014-08-12 12:26:15 -07:00
root . _clearCommError = function ( e ) {
if ( $rootScope . insightError > 0 )
$rootScope . insightError = - 1 ;
else
$rootScope . insightError = 0 ;
} ;
root . setSocketHandlers = function ( ) {
root . updateAddressList ( ) ;
if ( ! Socket . sysEventsSet ) {
Socket . sysOn ( 'error' , root . _setCommError ) ;
Socket . sysOn ( 'reconnect_error' , root . _setCommError ) ;
Socket . sysOn ( 'reconnect_failed' , root . _setCommError ) ;
Socket . sysOn ( 'connect' , root . _clearCommError ) ;
Socket . sysOn ( 'reconnect' , root . _clearCommError ) ;
Socket . sysEventsSet = true ;
}
if ( ! $rootScope . wallet ) return ;
2014-04-18 15:08:01 -07:00
2014-08-12 12:26:15 -07:00
var currentAddrs = Socket . getListeners ( ) ;
var allAddrs = $rootScope . addrInfos ;
2014-06-16 08:44:18 -07:00
2014-08-12 12:26:15 -07:00
var newAddrs = [ ] ;
for ( var i in allAddrs ) {
var a = allAddrs [ i ] ;
if ( ! currentAddrs [ a . addressStr ] )
newAddrs . push ( a ) ;
}
for ( var i = 0 ; i < newAddrs . length ; i ++ ) {
Socket . emit ( 'subscribe' , newAddrs [ i ] . addressStr ) ;
}
newAddrs . forEach ( function ( a ) {
Socket . on ( a . addressStr , function ( txid ) {
2014-06-24 08:57:15 -07:00
2014-08-12 12:26:15 -07:00
if ( ! a . isChange )
notification . funds ( 'Funds received!' , a . addressStr ) ;
2014-06-24 08:57:15 -07:00
2014-08-12 12:26:15 -07:00
root . updateBalance ( function ( ) {
$rootScope . $digest ( ) ;
2014-04-23 17:20:44 -07:00
} ) ;
2014-04-17 09:25:36 -07:00
} ) ;
2014-08-12 12:26:15 -07:00
} ) ;
2014-06-23 10:57:23 -07:00
2014-08-12 12:26:15 -07:00
if ( ! $rootScope . wallet . spendUnconfirmed && ! Socket . isListeningBlocks ( ) ) {
Socket . emit ( 'subscribe' , 'inv' ) ;
Socket . on ( 'block' , function ( block ) {
root . updateBalance ( function ( ) {
$rootScope . $digest ( ) ;
2014-06-23 10:57:23 -07:00
} ) ;
2014-08-12 12:26:15 -07:00
} ) ;
}
} ;
return root ;
} ) ;