copay/js/services/controllerUtils.js

424 lines
12 KiB
JavaScript
Raw Normal View History

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')
.factory('controllerUtils', function($rootScope, $sce, $location, $filter, notification, $timeout, uriHandler, rateService) {
2014-08-22 10:13:04 -07:00
var root = {};
2014-05-07 15:04:36 -07:00
2014-10-10 13:58:19 -07:00
root.redirIfNotComplete = function() {
var w = $rootScope.wallet;
if (w) {
if (!w.isReady()) {
$location.path('/copayers');
}
2014-10-10 13:58:19 -07:00
} else {
$location.path('/');
}
};
2014-08-22 10:13:04 -07:00
root.redirIfLogged = function() {
var w = $rootScope.wallet;
if (w) {
if (!w.isReady()) {
$location.path('/copayers');
} else {
2014-10-31 07:49:52 -07:00
$location.path('homeWallet');
}
2014-08-22 10:13:04 -07:00
}
};
2014-08-06 14:41:37 -07:00
2014-08-22 10:13:04 -07:00
root.logout = function() {
2014-10-29 19:23:16 -07:00
if ($rootScope.iden) {
2014-10-30 12:20:25 -07:00
$rootScope.iden.store(null, function() {
2014-10-29 19:23:16 -07:00
$rootScope.iden.close();
2014-06-24 08:57:15 -07:00
2014-10-30 12:20:25 -07:00
delete $rootScope['wallet'];
delete $rootScope['iden'];
2014-04-23 14:07:20 -07:00
2014-10-30 12:20:25 -07:00
// Clear rootScope
for (var i in $rootScope) {
if (i.charAt(0) != '$') {
delete $rootScope[i];
}
}
2014-06-12 07:03:24 -07:00
2014-10-30 12:20:25 -07:00
$location.path('/');
});
}
2014-08-22 10:13:04 -07:00
};
2014-06-12 07:03:24 -07:00
2014-08-22 10:13:04 -07:00
root.onError = function(scope) {
if (scope) scope.loading = false;
2014-08-12 12:26:15 -07:00
}
2014-08-22 10:13:04 -07:00
root.onErrorDigest = function(scope, msg) {
root.onError(scope);
if (msg) {
notification.error('Error', msg);
2014-08-12 12:26:15 -07:00
}
2014-08-22 10:13:04 -07:00
};
2014-07-08 04:58:24 -07:00
root.isFocusedWallet = function(wid) {
return $rootScope.wallet && wid === $rootScope.wallet.getId();
};
root.updateTxsAndBalance = _.debounce(function(w) {
root.updateTxs({
2014-10-31 07:14:09 -07:00
wallet: w,
pending: true,
});
root.updateBalance(w, function() {
$rootScope.$digest();
})
}, 3000);
root.installWalletHandlers = function($scope, w) {
var wid = w.getId();
w.on('connectionError', function() {
if (root.isFocusedWallet(wid)) {
var message = "Could not connect to the Insight server. Check your settings and network configuration";
notification.error('Networking Error', message);
root.onErrorDigest($scope);
}
2014-08-22 10:13:04 -07:00
});
2014-04-24 19:13:55 -07:00
2014-08-22 10:13:04 -07:00
w.on('corrupt', function(peerId) {
if (root.isFocusedWallet(wid)) {
notification.error('Error', $filter('translate')('Received corrupt message from ') + peerId);
}
2014-08-22 10:13:04 -07:00
});
w.on('ready', function(myPeerID) {
$scope.loading = false;
if ($rootScope.initialConnection) {
$rootScope.initialConnection = false;
if ($rootScope.pendingPayment) {
$location.path('send');
} else {
root.redirIfLogged();
}
2014-08-22 10:13:04 -07:00
}
});
2014-05-16 14:48:17 -07:00
w.on('tx', function(address, isChange) {
if (!isChange) {
notification.funds('Funds received on ' + w.getName(), address);
}
root.updateBalance(w, function() {
$rootScope.$digest();
});
});
w.on('balanceUpdated', function() {
root.updateBalance(w, function() {
$rootScope.$digest();
});
});
2014-09-09 16:55:51 -07:00
w.on('insightReconnected', function() {
$rootScope.reconnecting = false;
root.updateAddressList(w.getId());
root.updateBalance(w, function() {
$rootScope.$digest();
});
});
2014-09-09 16:55:51 -07:00
w.on('insightError', function() {
if (root.isFocusedWallet(wid)) {
$rootScope.reconnecting = true;
$rootScope.$digest();
}
});
2014-10-27 10:53:40 -07:00
w.on('newAddresses', function() {
root.updateTxsAndBalance(w);
});
2014-10-27 10:53:40 -07:00
w.on('txProposalsUpdated', function() {
root.updateTxsAndBalance(w);
2014-08-22 10:13:04 -07:00
});
2014-08-22 10:13:04 -07:00
w.on('txProposalEvent', function(e) {
// TODO: add wallet name notification
2014-08-22 10:13:04 -07:00
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
switch (e.type) {
case 'signed':
notification.info('Transaction Update', $filter('translate')('A transaction was signed by') + ' ' + user);
2014-08-22 10:13:04 -07:00
break;
case 'rejected':
notification.info('Transaction Update', $filter('translate')('A transaction was rejected by') + ' ' + user);
2014-08-22 10:13:04 -07:00
break;
case 'corrupt':
2014-09-29 13:36:34 -07:00
notification.error('Transaction Error', $filter('translate')('Received corrupt transaction from') + ' ' + user);
2014-08-22 10:13:04 -07:00
break;
}
});
w.on('addressBookUpdated', function(dontDigest) {
if (root.isFocusedWallet(wid)) {
if (!dontDigest) {
$rootScope.$digest();
}
2014-08-22 10:13:04 -07:00
}
});
w.on('connect', function(peerID) {
$rootScope.$digest();
2014-08-22 10:13:04 -07:00
});
w.on('close', root.onErrorDigest);
w.on('locked', root.onErrorDigest.bind(this));
};
root.setupGlobalVariables = function(iden) {
notification.enableHtml5Mode(); // for chrome: if support, enable it
uriHandler.register();
$rootScope.unitName = config.unitName;
$rootScope.txAlertCount = 0;
$rootScope.initialConnection = true;
$rootScope.reconnecting = false;
$rootScope.isCollapsed = true;
$rootScope.iden = iden;
// TODO
// $rootScope.$watch('txAlertCount', function(txAlertCount) {
// if (txAlertCount && txAlertCount > 0) {
//
// notification.info('New Transaction', ($rootScope.txAlertCount == 1) ? 'You have a pending transaction proposal' : $filter('translate')('You have') + ' ' + $rootScope.txAlertCount + ' ' + $filter('translate')('pending transaction proposals'), txAlertCount);
// }
// });
};
root.rebindWallets = function($scope, iden) {
_.each(iden.listWallets(), function(wallet) {
preconditions.checkState(wallet);
root.installWalletHandlers($scope, wallet);
});
};
root.setFocusedWallet = function(w) {
if (!_.isObject(w))
w = $rootScope.iden.getWalletById(w);
preconditions.checkState(w && _.isObject(w));
$rootScope.wallet = w;
w.updateTimestamp(new Date().getTime(), function() {
root.redirIfLogged();
root.updateBalance(w, function() {
$rootScope.$digest();
})
});
2014-08-22 10:13:04 -07:00
};
root.bindProfile = function($scope, iden, w) {
root.setupGlobalVariables(iden);
root.rebindWallets($scope, iden);
2014-10-15 13:18:30 -07:00
if (w) {
root.setFocusedWallet(w);
} else {
$location.path('/manage');
}
};
// On the focused wallet
root.updateAddressList = function(wid) {
if (!wid || root.isFocusedWallet(wid)) {
var w = $rootScope.wallet;
if (w && w.isReady()) {
$rootScope.addrInfos = w.getAddressesInfo();
}
}
2014-08-22 10:13:04 -07:00
};
2014-10-16 11:06:39 -07:00
var _balanceCache = {};
2014-10-16 12:02:32 -07:00
root.clearBalanceCache = function(w) {
delete _balanceCache[w.getId()];
};
2014-10-20 06:29:43 -07:00
root._computeBalance = function(w, cb) {
cb = cb || function() {};
var satToUnit = 1 / w.settings.unitToSatoshi;
var COIN = bitcore.util.COIN;
2014-10-16 11:06:39 -07:00
2014-10-20 06:29:43 -07:00
w.getBalance(function(err, balanceSat, balanceByAddrSat, safeBalanceSat) {
if (err) return cb(err);
2014-10-16 11:06:39 -07:00
2014-10-20 06:29:43 -07:00
var r = {};
r.totalBalance = balanceSat * satToUnit;
r.totalBalanceBTC = (balanceSat / COIN);
r.availableBalance = safeBalanceSat * satToUnit;
r.availableBalanceBTC = (safeBalanceSat / COIN);
2014-10-20 06:29:43 -07:00
r.lockedBalance = (balanceSat - safeBalanceSat) * satToUnit;
r.lockedBalanceBTC = (balanceSat - safeBalanceSat) / COIN;
var balanceByAddr = {};
for (var ii in balanceByAddrSat) {
balanceByAddr[ii] = balanceByAddrSat[ii] * satToUnit;
}
r.balanceByAddr = balanceByAddr;
root.updateAddressList();
r.updatingBalance = false;
2014-10-20 06:29:43 -07:00
rateService.whenAvailable(function() {
r.totalBalanceAlternative = rateService.toFiat(balanceSat, w.settings.alternativeIsoCode);
r.alternativeIsoCode = w.settings.alternativeIsoCode;
r.lockedBalanceAlternative = rateService.toFiat(balanceSat - safeBalanceSat, w.settings.alternativeIsoCode);
r.alternativeConversionRate = rateService.toFiat(100000000, w.settings.alternativeIsoCode);
return cb(null, r)
});
});
};
root._updateScope = function(w, data, $scope, cb) {
$scope.totalBalance = data.totalBalance;
$scope.totalBalanceBTC = data.totalBalanceBTC;
$scope.availableBalance = data.availableBalance;
$scope.availableBalanceBTC = data.availableBalanceBTC;
$scope.lockedBalance = data.lockedBalance;
$scope.lockedBalanceBTC = data.lockedBalanceBTC;
2014-10-16 11:06:39 -07:00
2014-10-20 06:29:43 -07:00
$scope.balanceByAddr = data.balanceByAddr;
$scope.totalBalanceAlternative = data.totalBalanceAlternative;
$scope.alternativeIsoCode = data.alternativeIsoCode;
$scope.lockedBalanceAlternative = data.lockedBalanceAlternative;
$scope.alternativeConversionRate = data.alternativeConversionRate;
if (cb) return cb();
};
root.updateBalance = function(w, cb) {
2014-10-16 11:06:39 -07:00
w = w || $rootScope.wallet;
if (!w) return root.onErrorDigest();
if (!w.isReady()) return;
console.log('## Updating balance of:' + w.id)
2014-10-20 06:29:43 -07:00
w.balanceInfo = {};
var scope = root.isFocusedWallet(w.id) ? $rootScope : w.balanceInfo;
2014-10-17 09:14:41 -07:00
root.updateAddressList();
2014-10-16 11:06:39 -07:00
var wid = w.getId();
if (_balanceCache[wid]) {
2014-10-20 06:29:43 -07:00
root._updateScope(w, _balanceCache[wid], scope, function() {
if (root.isFocusedWallet(w.id)) {
setTimeout(function() {
$rootScope.$digest();
}, 1);
}
});
2014-10-16 11:06:39 -07:00
} else {
2014-10-20 06:29:43 -07:00
scope.updatingBalance = true;
2014-10-16 11:06:39 -07:00
}
2014-10-20 06:29:43 -07:00
root._computeBalance(w, function(err, res) {
2014-10-16 11:06:39 -07:00
if (err) throw err;
2014-10-20 06:29:43 -07:00
_balanceCache[wid] = res;
root._updateScope(w, _balanceCache[wid], scope, function() {
scope.updatingBalance = false;
2014-10-17 09:14:41 -07:00
if (cb) cb();
2014-10-16 11:06:39 -07:00
});
2014-08-22 10:13:04 -07:00
});
};
2014-08-22 10:13:04 -07:00
root.updateTxs = function(opts) {
var w = opts.wallet || $rootScope.wallet;
2014-08-22 10:13:04 -07:00
if (!w) return;
opts = opts || $rootScope.txsOpts || {};
var satToUnit = 1 / w.settings.unitToSatoshi;
2014-08-22 10:13:04 -07:00
var myCopayerId = w.getMyCopayerId();
var pendingForUs = 0;
var inT = w.getTxProposals().sort(function(t1, t2) {
return t2.createdTs - t1.createdTs
});
var txs = [];
inT.forEach(function(i, index) {
if (opts.skip && (index < opts.skip[0] || index >= opts.skip[1])) {
return txs.push(null);
}
2014-09-29 13:36:34 -07:00
if (i.isPending && myCopayerId != i.creator && !i.rejectedByUs && !i.signedByUs) {
2014-08-22 10:13:04 -07:00
pendingForUs++;
}
if (!!opts.pending == !!i.isPending) {
var tx = i.builder.build();
var outs = [];
tx.outs.forEach(function(o) {
2014-09-11 11:29:45 -07:00
var addr = bitcore.Address.fromScriptPubKey(o.getScript(), w.getNetworkName())[0].toString();
2014-08-22 10:13:04 -07:00
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);
}
});
// Disabling this as discrepancies in local time on copayer machines is causing
// valid TXPs to get removed
//w.removeTxWithSpentInputs();
2014-09-29 13:36:34 -07:00
2014-08-22 10:13:04 -07:00
$rootScope.txs = txs;
$rootScope.txsOpts = opts;
if ($rootScope.pendingTxCount < pendingForUs) {
$rootScope.txAlertCount = pendingForUs;
2014-08-12 12:26:15 -07:00
}
2014-08-22 10:13:04 -07:00
$rootScope.pendingTxCount = pendingForUs;
};
2014-08-12 12:26:15 -07:00
2014-10-21 10:26:58 -07:00
root.deleteWallet = function($scope, w) {
w = w || $rootScope.wallet;
$rootScope.iden.deleteWallet(w.id, function() {
notification.info('Wallet deleted', $filter('translate')('Wallet deleted'));
$rootScope.wallet = null;
var lastFocused = $rootScope.iden.getLastFocusedWallet();
2014-10-21 10:26:58 -07:00
root.bindProfile($scope, $rootScope.iden, lastFocused);
});
};
root.getActionList = function(actions) {
return getActionList(actions);
};
2014-08-22 10:13:04 -07:00
function getActionList(actions) {
var peers = Object.keys(actions).map(function(i) {
return {
cId: i,
actions: actions[i]
}
});
return peers.sort(function(a, b) {
return !!b.actions.create - !!a.actions.create;
});
}
2014-08-22 10:13:04 -07:00
return root;
});