284 lines
8.2 KiB
JavaScript
284 lines
8.2 KiB
JavaScript
'use strict';
|
|
|
|
angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $log, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, bwcError, gettextCatalog, lodash, walletService, popupService, $ionicHistory) {
|
|
var isGlidera = $scope.isGlidera;
|
|
var GLIDERA_LOCK_TIME = 6 * 60 * 60;
|
|
var now = Math.floor(Date.now() / 1000);
|
|
var countDown;
|
|
|
|
$scope.init = function() {
|
|
$scope.loading = null;
|
|
$scope.isCordova = platformInfo.isCordova;
|
|
$scope.copayerId = $scope.wallet.credentials.copayerId;
|
|
$scope.isShared = $scope.wallet.credentials.n > 1;
|
|
$scope.canSign = $scope.wallet.canSign() || $scope.wallet.isPrivKeyExternal();
|
|
$scope.color = $scope.wallet.color;
|
|
$scope.data = {};
|
|
$scope.displayAmount = getDisplayAmount($scope.tx.amountStr);
|
|
$scope.displayUnit = getDisplayUnit($scope.tx.amountStr);
|
|
initActionList();
|
|
checkPaypro();
|
|
applyButtonText();
|
|
};
|
|
|
|
function applyButtonText() {
|
|
$scope.buttonText = $scope.isCordova ? gettextCatalog.getString('Slide') + ' ' : gettextCatalog.getString('Click') + ' ';
|
|
|
|
var lastSigner = lodash.filter($scope.tx.actions, {
|
|
type: 'accept'
|
|
}).length == $scope.tx.requiredSignatures - 1;
|
|
|
|
if (lastSigner)
|
|
$scope.buttonText += gettextCatalog.getString('to send');
|
|
else
|
|
$scope.buttonText += gettextCatalog.getString('to accept');
|
|
};
|
|
|
|
function getDisplayAmount(amountStr) {
|
|
return amountStr.split(' ')[0];
|
|
};
|
|
|
|
function getDisplayUnit(amountStr) {
|
|
return amountStr.split(' ')[1];
|
|
};
|
|
|
|
function initActionList() {
|
|
$scope.actionList = [];
|
|
|
|
if (!$scope.isShared) return;
|
|
|
|
var actionDescriptions = {
|
|
created: gettextCatalog.getString('Proposal Created'),
|
|
accept: gettextCatalog.getString('Accepted'),
|
|
reject: gettextCatalog.getString('Rejected'),
|
|
broadcasted: gettextCatalog.getString('Broadcasted'),
|
|
};
|
|
|
|
$scope.actionList.push({
|
|
type: 'created',
|
|
time: $scope.tx.createdOn,
|
|
description: actionDescriptions['created'],
|
|
by: $scope.tx.creatorName
|
|
});
|
|
|
|
lodash.each($scope.tx.actions, function(action) {
|
|
$scope.actionList.push({
|
|
type: action.type,
|
|
time: action.createdOn,
|
|
description: actionDescriptions[action.type],
|
|
by: action.copayerName
|
|
});
|
|
});
|
|
|
|
$timeout(function() {
|
|
$scope.actionList.reverse();
|
|
}, 10);
|
|
};
|
|
|
|
function checkPaypro() {
|
|
if ($scope.tx.payProUrl && !platformInfo.isChromeApp) {
|
|
$scope.wallet.fetchPayPro({
|
|
payProUrl: $scope.tx.payProUrl,
|
|
}, function(err, paypro) {
|
|
if (err) return;
|
|
$scope.tx.paypro = paypro;
|
|
paymentTimeControl($scope.tx.paypro.expires);
|
|
$timeout(function() {
|
|
$ionicScrollDelegate.resize();
|
|
}, 10);
|
|
});
|
|
}
|
|
};
|
|
|
|
function paymentTimeControl(expirationTime) {
|
|
$scope.paymentExpired = false;
|
|
setExpirationTime();
|
|
|
|
countDown = $interval(function() {
|
|
setExpirationTime();
|
|
}, 1000);
|
|
|
|
function setExpirationTime() {
|
|
var now = Math.floor(Date.now() / 1000);
|
|
if (now > expirationTime) {
|
|
$scope.paymentExpired = true;
|
|
if (countDown) $interval.cancel(countDown);
|
|
return;
|
|
}
|
|
var totalSecs = expirationTime - now;
|
|
var m = Math.floor(totalSecs / 60);
|
|
var s = totalSecs % 60;
|
|
$scope.expires = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2);
|
|
};
|
|
};
|
|
|
|
$scope.$on('accepted', function(event) {
|
|
$scope.sign();
|
|
});
|
|
|
|
// ToDo: use tx.customData instead of tx.message
|
|
if ($scope.tx.message === 'Glidera transaction' && isGlidera) {
|
|
$scope.tx.isGlidera = true;
|
|
if ($scope.tx.canBeRemoved) {
|
|
$scope.tx.canBeRemoved = (Date.now() / 1000 - ($scope.tx.ts || $scope.tx.createdOn)) > GLIDERA_LOCK_TIME;
|
|
}
|
|
}
|
|
|
|
var setError = function(err, prefix) {
|
|
$scope.sendStatus = '';
|
|
$scope.loading = false;
|
|
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, prefix));
|
|
};
|
|
|
|
$scope.sign = function(onSendStatusChange) {
|
|
$scope.loading = true;
|
|
walletService.publishAndSign($scope.wallet, $scope.tx, function(err, txp) {
|
|
$scope.$emit('UpdateTx');
|
|
if (err) return setError(err, gettextCatalog.getString('Could not send payment'));
|
|
success();
|
|
}, onSendStatusChange);
|
|
};
|
|
|
|
$scope.reject = function(txp) {
|
|
var title = gettextCatalog.getString('Warning!');
|
|
var msg = gettextCatalog.getString('Are you sure you want to reject this transaction?');
|
|
popupService.showConfirm(title, msg, null, null, function(res) {
|
|
if (res) {
|
|
$scope.loading = true;
|
|
|
|
walletService.reject($scope.wallet, $scope.tx, function(err, txpr) {
|
|
if (err)
|
|
return setError(err, gettextCatalog.getString('Could not reject payment'));
|
|
|
|
$scope.close();
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.remove = function() {
|
|
var title = gettextCatalog.getString('Warning!');
|
|
var msg = gettextCatalog.getString('Are you sure you want to remove this transaction?');
|
|
popupService.showConfirm(title, msg, null, null, function(res) {
|
|
if (res) {
|
|
ongoingProcess.set('removeTx', true);
|
|
walletService.removeTx($scope.wallet, $scope.tx, function(err) {
|
|
ongoingProcess.set('removeTx', false);
|
|
|
|
// Hacky: request tries to parse an empty response
|
|
if (err && !(err.message && err.message.match(/Unexpected/))) {
|
|
$scope.$emit('UpdateTx');
|
|
return setError(err, gettextCatalog.getString('Could not delete payment proposal'));
|
|
}
|
|
|
|
$scope.close();
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.broadcast = function(txp) {
|
|
$scope.loading = true;
|
|
|
|
$timeout(function() {
|
|
ongoingProcess.set('broadcastingTx', true);
|
|
walletService.broadcastTx($scope.wallet, $scope.tx, function(err, txpb) {
|
|
ongoingProcess.set('broadcastingTx', false);
|
|
|
|
if (err) {
|
|
return setError(err, gettextCatalog.getString('Could not broadcast payment'));
|
|
}
|
|
|
|
$scope.close();
|
|
});
|
|
}, 10);
|
|
};
|
|
|
|
$scope.getShortNetworkName = function() {
|
|
return $scope.wallet.credentials.networkName.substring(0, 4);
|
|
};
|
|
|
|
var updateTxInfo = function(eventName) {
|
|
$scope.wallet.getTx($scope.tx.id, function(err, tx) {
|
|
if (err) {
|
|
if (err.message && err.message == 'Transaction proposal not found' &&
|
|
(eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) {
|
|
$scope.tx.removed = true;
|
|
$scope.tx.canBeRemoved = false;
|
|
$scope.tx.pendingForUs = false;
|
|
$scope.$apply();
|
|
}
|
|
return;
|
|
}
|
|
|
|
var action = lodash.find(tx.actions, {
|
|
copayerId: $scope.wallet.credentials.copayerId
|
|
});
|
|
|
|
$scope.tx = txFormatService.processTx(tx);
|
|
|
|
if (!action && tx.status == 'pending')
|
|
$scope.tx.pendingForUs = true;
|
|
|
|
$scope.updateCopayerList();
|
|
initActionList();
|
|
$scope.$apply();
|
|
});
|
|
};
|
|
|
|
var bwsEvent = $rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
|
lodash.each([
|
|
'TxProposalRejectedBy',
|
|
'TxProposalAcceptedBy',
|
|
'transactionProposalRemoved',
|
|
'TxProposalRemoved',
|
|
'NewOutgoingTx',
|
|
'UpdateTx'
|
|
], function(eventName) {
|
|
if (walletId == $scope.wallet.id && type == eventName) {
|
|
updateTxInfo(eventName);
|
|
}
|
|
});
|
|
});
|
|
|
|
$scope.updateCopayerList = function() {
|
|
lodash.map($scope.copayers, function(cp) {
|
|
lodash.each($scope.tx.actions, function(ac) {
|
|
if (cp.id == ac.copayerId) {
|
|
cp.action = ac.type;
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
function statusChangeHandler(processName, showName, isOn) {
|
|
$log.debug('statusChangeHandler: ', processName, showName, isOn);
|
|
if (showName) {
|
|
$scope.sendStatus = showName;
|
|
}
|
|
}
|
|
|
|
function success() {
|
|
$scope.sendStatus = 'success';
|
|
$scope.$digest();
|
|
}
|
|
|
|
$scope.statusChangeHandler = statusChangeHandler;
|
|
|
|
$scope.onConfirm = function() {
|
|
$scope.sign(statusChangeHandler);
|
|
};
|
|
|
|
$scope.onSuccessConfirm = function() {
|
|
$ionicHistory.nextViewOptions({
|
|
disableAnimate: true
|
|
});
|
|
$scope.close();
|
|
};
|
|
|
|
$scope.close = function() {
|
|
bwsEvent();
|
|
$scope.loading = null;
|
|
$scope.txpDetailsModal.hide();
|
|
};
|
|
});
|