Wallet/src/js/controllers/confirm.js

678 lines
20 KiB
JavaScript
Raw Normal View History

2016-08-16 18:38:18 -03:00
'use strict';
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService) {
2017-06-20 12:14:21 -03:00
2016-10-20 15:38:57 -03:00
var countDown = null;
2017-06-21 13:03:48 -03:00
var CONFIRM_LIMIT_USD = 20;
2017-06-22 11:38:13 -03:00
var FEE_TOO_HIGH_LIMIT_PER = 15;
2017-06-20 12:14:21 -03:00
var tx = {};
// Config Related values
var config = configService.getSync();
var walletConfig = config.wallet;
var unitToSatoshi = walletConfig.settings.unitToSatoshi;
var unitDecimals = walletConfig.settings.unitDecimals;
var satToUnit = 1 / unitToSatoshi;
var configFeeLevel = walletConfig.settings.feeLevel ? walletConfig.settings.feeLevel : 'normal';
// Platform info
var isChromeApp = platformInfo.isChromeApp;
var isCordova = platformInfo.isCordova;
var isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP;
2017-06-20 12:14:21 -03:00
2017-07-10 14:19:38 -03:00
//custom fee flag
var usingCustomFee = null;
2017-06-22 00:46:35 -03:00
function refresh() {
$timeout(function() {
$scope.$apply();
}, 10);
2017-06-22 00:46:35 -03:00
}
2017-06-20 12:14:21 -03:00
$scope.showWalletSelector = function() {
$scope.walletSelector = true;
2017-06-22 00:46:35 -03:00
refresh();
2017-06-20 12:14:21 -03:00
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
2017-06-21 17:09:33 -03:00
function exitWithError(err) {
$log.info('Error setting wallet selector:' + err);
popupService.showAlert(gettextCatalog.getString(), bwcError.msg(err), function() {
$ionicHistory.nextViewOptions({
disableAnimate: true,
historyRoot: true
});
$ionicHistory.clearHistory();
$state.go('tabs.send');
});
};
2017-09-15 10:22:51 -03:00
function setNoWallet(msg, criticalError) {
2017-06-21 17:09:33 -03:00
$scope.wallet = null;
2017-07-11 12:28:47 -03:00
$scope.noWalletMessage = msg;
2017-09-15 10:22:51 -03:00
$scope.criticalError = criticalError;
2017-06-21 17:09:33 -03:00
$log.warn('Not ready to make the payment:' + msg);
$timeout(function() {
$scope.$apply();
});
};
$scope.$on("$ionicView.beforeEnter", function(event, data) {
2017-09-01 15:26:12 -03:00
function setWalletSelector(coin, network, minAmount, cb) {
2017-06-21 18:29:03 -03:00
// no min amount? (sendMax) => look for no empty wallets
2017-06-22 00:46:35 -03:00
minAmount = minAmount || 1;
2017-06-21 18:29:03 -03:00
2017-06-20 12:14:21 -03:00
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: network,
2017-09-01 15:26:12 -03:00
coin: coin
2017-06-20 12:14:21 -03:00
});
if (tx.fromWalletId) {
$scope.wallets = lodash.filter($scope.wallets, function(w) {
return w.id == tx.fromWalletId;
});
}
2017-06-20 12:14:21 -03:00
if (!$scope.wallets || !$scope.wallets.length) {
2017-09-15 10:22:51 -03:00
setNoWallet(gettextCatalog.getString('No wallets available'), true);
2017-06-21 17:09:33 -03:00
return cb();
2017-06-20 12:14:21 -03:00
}
var filteredWallets = [];
var index = 0;
var walletsUpdated = 0;
lodash.each($scope.wallets, function(w) {
walletService.getStatus(w, {}, function(err, status) {
if (err || !status) {
$log.error(err);
} else {
walletsUpdated++;
w.status = status;
if (!status.availableBalanceSat)
$log.debug('No balance available in: ' + w.name);
if (status.availableBalanceSat > minAmount) {
filteredWallets.push(w);
}
}
if (++index == $scope.wallets.length) {
if (!walletsUpdated)
return cb('Could not update any wallet');
if (lodash.isEmpty(filteredWallets)) {
2017-09-15 10:22:51 -03:00
setNoWallet(gettextCatalog.getString('Insufficient funds'), true);
2017-06-20 12:14:21 -03:00
}
$scope.wallets = lodash.clone(filteredWallets);
return cb();
}
});
});
};
// Setup $scope
2017-09-15 16:06:06 -03:00
2017-10-02 12:35:08 -03:00
var B = data.stateParams.coin == 'bch' ? bitcoreCash : bitcore;
var networkName;
try {
networkName = (new B.Address(data.stateParams.toAddress)).network.name;
} catch(e) {
var message = gettextCatalog.getString('Copay only supports Bitcoin Cash using new version numbers addresses');
2017-10-02 12:40:44 -03:00
var backText = gettextCatalog.getString('Go back');
var learnText = gettextCatalog.getString('Learn more');
popupService.showConfirm(null, message, backText, learnText, function(back) {
2017-10-02 12:35:08 -03:00
$ionicHistory.nextViewOptions({
disableAnimate: true,
historyRoot: true
});
$state.go('tabs.send').then(function() {
$ionicHistory.clearHistory();
if (!back) {
var url = 'https://support.bitpay.com/hc/en-us/articles/115004671663';
externalLinkService.open(url);
2017-10-02 12:35:08 -03:00
}
});
});
return;
}
2017-06-20 12:14:21 -03:00
// Grab stateParams
tx = {
toAmount: parseInt(data.stateParams.toAmount),
sendMax: data.stateParams.useSendMax == 'true' ? true : false,
fromWalletId: data.stateParams.fromWalletId,
2017-10-02 12:35:08 -03:00
toAddress: data.stateParams.toAddress,
displayAddress: data.stateParams.displayAddress,
2017-06-20 12:14:21 -03:00
description: data.stateParams.description,
paypro: data.stateParams.paypro,
2017-09-01 15:26:12 -03:00
feeLevel: configFeeLevel,
2017-06-20 12:14:21 -03:00
spendUnconfirmed: walletConfig.spendUnconfirmed,
// Vanity tx info (not in the real tx)
recipientType: data.stateParams.recipientType || null,
toName: data.stateParams.toName,
toEmail: data.stateParams.toEmail,
toColor: data.stateParams.toColor,
2017-10-02 12:35:08 -03:00
network: networkName,
2017-08-27 23:50:27 -03:00
coin: data.stateParams.coin,
2017-06-21 13:03:48 -03:00
txp: {},
2017-06-20 12:14:21 -03:00
};
2017-09-01 15:26:12 -03:00
if (tx.coin && tx.coin == 'bch') tx.feeLevel = 'normal';
2017-06-20 12:14:21 -03:00
// Other Scope vars
$scope.isCordova = isCordova;
$scope.isWindowsPhoneApp = isWindowsPhoneApp;
2017-02-22 15:08:51 -05:00
$scope.showAddress = false;
$scope.walletSelectorTitle = gettextCatalog.getString('Send from');
2017-06-22 00:46:35 -03:00
2017-09-01 15:26:12 -03:00
setWalletSelector(tx.coin, tx.network, tx.toAmount, function(err) {
if (err) {
return exitWithError('Could not update wallets');
}
2017-06-20 12:14:21 -03:00
if ($scope.wallets.length > 1) {
$scope.showWalletSelector();
} else if ($scope.wallets.length) {
setWallet($scope.wallets[0], tx);
}
});
2017-06-20 12:14:21 -03:00
});
2017-05-16 14:21:33 -03:00
2017-06-21 18:29:03 -03:00
function getSendMaxInfo(tx, wallet, cb) {
2017-06-20 12:14:21 -03:00
if (!tx.sendMax) return cb();
2017-01-16 16:25:12 -03:00
2017-06-20 12:14:21 -03:00
//ongoingProcess.set('retrievingInputs', true);
walletService.getSendMaxInfo(wallet, {
feePerKb: tx.feeRate,
excludeUnconfirmedUtxos: !tx.spendUnconfirmed,
returnInputs: true,
}, cb);
2017-01-16 16:25:12 -03:00
};
2016-09-20 15:28:31 -03:00
2017-06-20 12:14:21 -03:00
function getTxp(tx, wallet, dryRun, cb) {
// ToDo: use a credential's (or fc's) function for this
if (tx.description && !wallet.credentials.sharedEncryptingKey) {
2017-06-20 12:14:21 -03:00
var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key');
$log.warn(msg);
return setSendError(msg);
}
if (tx.toAmount > Number.MAX_SAFE_INTEGER) {
var msg = gettextCatalog.getString('Amount too big');
$log.warn(msg);
return setSendError(msg);
2016-11-29 14:28:43 -03:00
}
2016-10-10 13:57:25 -03:00
2017-06-20 12:14:21 -03:00
var txp = {};
2016-09-20 15:28:31 -03:00
2017-06-20 12:14:21 -03:00
txp.outputs = [{
'toAddress': tx.toAddress,
'amount': tx.toAmount,
'message': tx.description
}];
if (tx.sendMaxInfo) {
txp.inputs = tx.sendMaxInfo.inputs;
txp.fee = tx.sendMaxInfo.fee;
} else {
2017-07-10 14:19:38 -03:00
if (usingCustomFee) {
2017-07-07 10:26:31 -03:00
txp.feePerKb = tx.feeRate;
} else txp.feeLevel = tx.feeLevel;
2017-06-20 12:14:21 -03:00
}
txp.message = tx.description;
2017-06-20 12:14:21 -03:00
if (tx.paypro) {
txp.payProUrl = tx.paypro.url;
}
txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed;
txp.dryRun = dryRun;
walletService.createTx(wallet, txp, function(err, ctxp) {
if (err) {
setSendError(err);
return cb(err);
}
return cb(null, ctxp);
});
};
2017-06-21 13:03:48 -03:00
function updateTx(tx, wallet, opts, cb) {
ongoingProcess.set('calculatingFee', true);
2017-06-20 12:14:21 -03:00
2017-06-21 13:03:48 -03:00
if (opts.clearCache) {
tx.txp = {};
}
2017-06-20 12:14:21 -03:00
2017-06-21 13:03:48 -03:00
$scope.tx = tx;
2017-06-20 12:14:21 -03:00
2017-06-21 18:29:03 -03:00
function updateAmount() {
if (!tx.toAmount) return;
2017-06-20 12:14:21 -03:00
2017-06-21 18:29:03 -03:00
// Amount
2017-08-28 15:51:13 -03:00
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.toAmount);
2017-06-21 18:29:03 -03:00
tx.amountValueStr = tx.amountStr.split(' ')[0];
tx.amountUnitStr = tx.amountStr.split(' ')[1];
2017-08-28 15:51:13 -03:00
txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) {
2017-06-21 18:29:03 -03:00
tx.alternativeAmountStr = v;
});
}
updateAmount();
refresh();
2017-06-20 12:14:21 -03:00
2017-06-23 08:52:45 -03:00
// End of quick refresh, before wallet is selected.
if (!wallet) {
ongoingProcess.set('calculatingFee', false);
return cb();
}
2017-06-23 08:52:45 -03:00
2017-08-29 15:47:39 -03:00
feeService.getFeeRate(wallet.coin, tx.network, tx.feeLevel, function(err, feeRate) {
if (err) {
ongoingProcess.set('calculatingFee', false);
return cb(err);
}
2017-06-20 12:14:21 -03:00
2017-07-10 14:19:38 -03:00
if (!usingCustomFee) tx.feeRate = feeRate;
2017-06-20 12:14:21 -03:00
tx.feeLevelName = feeService.feeOpts[tx.feeLevel];
2017-06-21 18:29:03 -03:00
getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) {
2017-06-20 12:14:21 -03:00
if (err) {
ongoingProcess.set('calculatingFee', false);
2017-06-20 12:14:21 -03:00
var msg = gettextCatalog.getString('Error getting SendMax information');
return setSendError(msg);
}
if (sendMaxInfo) {
2017-06-21 18:29:03 -03:00
$log.debug('Send max info', sendMaxInfo);
if (tx.sendMax && sendMaxInfo.amount == 0) {
ongoingProcess.set('calculatingFee', false);
2017-07-11 14:33:50 -03:00
setNoWallet(gettextCatalog.getString('Insufficient funds'));
2017-06-20 12:14:21 -03:00
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'));
return cb('no_funds');
2016-10-10 13:57:25 -03:00
}
2017-06-20 12:14:21 -03:00
2017-06-21 18:29:03 -03:00
tx.sendMaxInfo = sendMaxInfo;
2017-06-22 00:46:35 -03:00
tx.toAmount = tx.sendMaxInfo.amount;
2017-06-21 18:29:03 -03:00
updateAmount();
ongoingProcess.set('calculatingFee', false);
$timeout(function() {
showSendMaxWarning(wallet, sendMaxInfo);
}, 200);
2016-09-20 15:28:31 -03:00
}
2017-06-21 13:03:48 -03:00
// txp already generated for this wallet?
2017-06-23 10:38:05 -03:00
if (tx.txp[wallet.id]) {
ongoingProcess.set('calculatingFee', false);
2017-06-23 10:38:05 -03:00
refresh();
2017-06-21 13:03:48 -03:00
return cb();
2017-06-23 10:38:05 -03:00
}
2017-06-21 13:03:48 -03:00
getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) {
ongoingProcess.set('calculatingFee', false);
if (err) {
return cb(err);
}
2017-01-16 16:58:42 -03:00
2017-08-28 15:51:13 -03:00
txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee);
txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) {
2017-06-21 13:03:48 -03:00
txp.alternativeFeeStr = v;
if (txp.alternativeFeeStr.substring(0, 4) == '0.00')
txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr;
});
2017-06-22 11:38:13 -03:00
var per = (txp.fee / (txp.amount + txp.fee) * 100);
var perString = per.toFixed(2);
txp.feeRatePerStr = (perString == '0.00' ? '< ' : '') + perString + '%';
2017-07-07 10:26:31 -03:00
txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PER;
2017-06-20 12:14:21 -03:00
tx.txp[wallet.id] = txp;
2017-06-21 13:03:48 -03:00
$log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx);
2017-06-23 10:38:05 -03:00
refresh();
2017-06-20 12:14:21 -03:00
return cb();
});
2016-09-20 15:28:31 -03:00
});
});
2017-06-20 12:14:21 -03:00
}
2017-06-20 12:14:21 -03:00
function useSelectedWallet() {
2017-02-22 15:08:51 -05:00
2017-06-20 12:14:21 -03:00
if (!$scope.useSendMax) {
showAmount(tx.toAmount);
}
2017-06-20 12:14:21 -03:00
$scope.onWalletSelect($scope.wallet);
}
2016-09-20 15:28:31 -03:00
2017-06-20 12:14:21 -03:00
function setButtonText(isMultisig, isPayPro) {
2016-11-29 14:28:43 -03:00
2017-06-20 12:14:21 -03:00
if (isPayPro) {
2017-09-04 15:48:11 -03:00
if (isCordova && !isWindowsPhoneApp) {
$scope.buttonText = gettextCatalog.getString('Slide to pay');
} else {
$scope.buttonText = gettextCatalog.getString('Click to pay');
}
2017-06-20 12:14:21 -03:00
} else if (isMultisig) {
2017-09-04 15:48:11 -03:00
if (isCordova && !isWindowsPhoneApp) {
$scope.buttonText = gettextCatalog.getString('Slide to accept');
} else {
$scope.buttonText = gettextCatalog.getString('Click to accept');
}
} else {
if (isCordova && !isWindowsPhoneApp) {
$scope.buttonText = gettextCatalog.getString('Slide to send');
} else {
$scope.buttonText = gettextCatalog.getString('Click to send');
}
}
};
2017-06-20 12:14:21 -03:00
$scope.toggleAddress = function() {
$scope.showAddress = !$scope.showAddress;
};
2016-11-23 11:23:19 -03:00
function showSendMaxWarning(wallet, sendMaxInfo) {
2016-11-23 11:23:19 -03:00
2017-06-20 12:14:21 -03:00
function verifyExcludedUtxos() {
var warningMsg = [];
if (sendMaxInfo.utxosBelowFee > 0) {
warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", {
2017-08-28 15:51:13 -03:00
amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee)
2017-06-20 12:14:21 -03:00
}));
}
2016-11-23 11:23:19 -03:00
2017-06-20 12:14:21 -03:00
if (sendMaxInfo.utxosAboveMaxSize > 0) {
warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", {
2017-08-28 15:51:13 -03:00
amountAboveMaxSizeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountAboveMaxSize)
2017-06-20 12:14:21 -03:00
}));
}
return warningMsg.join('\n');
};
2016-11-23 11:23:19 -03:00
2017-06-20 12:14:21 -03:00
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", {
2017-08-28 15:51:13 -03:00
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee)
2016-11-23 11:23:19 -03:00
});
2017-06-20 12:14:21 -03:00
var warningMsg = verifyExcludedUtxos();
if (!lodash.isEmpty(warningMsg))
msg += '\n' + warningMsg;
popupService.showAlert(null, msg, function() {});
2016-11-23 11:23:19 -03:00
};
$scope.onWalletSelect = function(wallet) {
2017-06-20 12:14:21 -03:00
setWallet(wallet, tx);
2016-10-12 18:49:00 -04:00
};
2017-06-21 13:03:48 -03:00
$scope.showDescriptionPopup = function(tx) {
2016-09-23 12:07:56 -03:00
var message = gettextCatalog.getString('Add description');
2016-09-16 21:01:19 -03:00
var opts = {
2017-06-21 13:03:48 -03:00
defaultText: tx.description
2016-09-07 16:48:16 -03:00
};
2016-09-23 12:07:56 -03:00
popupService.showPrompt(null, message, opts, function(res) {
2017-06-21 13:03:48 -03:00
if (typeof res != 'undefined') tx.description = res;
2016-09-23 12:07:56 -03:00
$timeout(function() {
$scope.$apply();
});
2016-08-24 15:47:36 -03:00
});
};
2016-10-20 15:38:57 -03:00
function _paymentTimeControl(expirationTime) {
2017-06-22 00:46:35 -03:00
$scope.paymentExpired = false;
2016-10-20 15:38:57 -03:00
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;
2017-06-22 00:46:35 -03:00
$scope.remainingTimeStr = ('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() {
2017-06-22 00:46:35 -03:00
$scope.paymentExpired = true;
$scope.remainingTimeStr = gettextCatalog.getString('Expired');
2016-10-20 15:38:57 -03:00
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
2017-06-20 12:14:21 -03:00
/* sets a wallet on the UI, creates a TXPs for that wallet */
function setWallet(wallet, tx) {
$scope.wallet = wallet;
2016-08-18 14:51:35 -03:00
// If select another wallet
tx.coin = wallet.coin;
tx.feeLevel = wallet.coin == 'bch' ? 'normal' : configFeeLevel;
usingCustomFee = null;
2017-06-20 12:14:21 -03:00
setButtonText(wallet.credentials.m > 1, !!tx.paypro);
2017-06-22 00:46:35 -03:00
if (tx.paypro)
_paymentTimeControl(tx.paypro.expires);
2017-06-20 12:14:21 -03:00
2017-06-21 13:03:48 -03:00
updateTx(tx, wallet, {
dryRun: true
}, function(err) {
2017-06-20 12:14:21 -03:00
$timeout(function() {
$ionicScrollDelegate.resize();
$scope.$apply();
}, 10);
});
2016-11-24 16:26:15 -03:00
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) {
$scope.sendStatus = '';
2016-10-17 14:46:51 -03:00
$timeout(function() {
$scope.$apply();
});
2016-12-13 14:21:57 -03:00
popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg));
2016-08-17 13:16:06 -03:00
};
2016-08-16 18:38:18 -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();
});
};
$scope.cancel = function() {
$scope.payproModal.hide();
};
2017-06-21 13:03:48 -03:00
$scope.approve = function(tx, wallet, onSendStatusChange) {
2016-12-05 11:17:48 -03:00
2017-06-21 13:03:48 -03:00
if (!tx || !wallet) return;
2016-12-05 11:17:48 -03:00
2017-06-22 00:46:35 -03:00
if ($scope.paymentExpired) {
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-10-07 20:03:51 -04:00
ongoingProcess.set('creatingTx', true, onSendStatusChange);
2017-06-21 13:03:48 -03:00
getTxp(lodash.clone(tx), wallet, false, function(err, txp) {
2016-10-07 20:03:51 -04:00
ongoingProcess.set('creatingTx', false, onSendStatusChange);
2016-12-16 14:54:16 -03:00
if (err) return;
2016-09-21 11:47:19 -03:00
2017-06-21 13:03:48 -03:00
// confirm txs for more that 20usd, if not spending/touchid is enabled
function confirmTx(cb) {
if (walletService.isEncrypted(wallet))
return cb();
2017-08-28 15:51:13 -03:00
var amountUsd = parseFloat(txFormatService.formatToUSD(wallet.coin, txp.amount));
2017-06-21 13:03:48 -03:00
if (amountUsd <= CONFIRM_LIMIT_USD)
return cb();
var message = gettextCatalog.getString('Sending {{amountStr}} from your {{name}} wallet', {
amountStr: tx.amountStr,
name: wallet.name
});
var okText = gettextCatalog.getString('Confirm');
var cancelText = gettextCatalog.getString('Cancel');
popupService.showConfirm(null, message, okText, cancelText, function(ok) {
return cb(!ok);
});
};
function publishAndSign() {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
$log.info('No signing proposal: No private key');
return walletService.onlyPublish(wallet, txp, function(err) {
if (err) setSendError(err);
}, onSendStatusChange);
}
walletService.publishAndSign(wallet, txp, function(err, txp) {
if (err) return setSendError(err);
2017-07-14 15:45:18 -03:00
if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) {
txConfirmNotification.subscribe(wallet, {
2017-07-14 10:18:36 -03:00
txid: txp.txid
});
}
2017-06-21 13:03:48 -03:00
}, onSendStatusChange);
};
confirmTx(function(nok) {
if (nok) {
$scope.sendStatus = '';
$timeout(function() {
$scope.$apply();
2016-09-21 11:47:19 -03:00
});
2017-06-21 13:03:48 -03:00
return;
2016-09-21 11:47:19 -03:00
}
2017-06-21 13:03:48 -03:00
publishAndSign();
});
2016-09-21 11:47:19 -03:00
});
};
function statusChangeHandler(processName, showName, isOn) {
2016-10-11 10:19:05 -03:00
$log.debug('statusChangeHandler: ', processName, showName, isOn);
if (
(
2017-02-20 10:25:52 -05:00
processName === 'broadcastingTx' ||
((processName === 'signingTx') && $scope.wallet.m > 1) ||
2017-01-13 01:21:32 -03:00
(processName == 'sendingTx' && !$scope.wallet.canSign() && !$scope.wallet.isPrivKeyExternal())
) && !isOn) {
2016-10-07 20:03:51 -04:00
$scope.sendStatus = 'success';
firebaseEventsService.logEvent('sent_bitcoin', { coin: $scope.wallet.coin });
2016-12-19 11:50:49 -03:00
$timeout(function() {
$scope.$digest();
2017-01-13 01:21:32 -03:00
}, 100);
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
$scope.statusChangeHandler = statusChangeHandler;
2016-10-07 20:03:51 -04:00
$scope.onSuccessConfirm = function() {
$scope.sendStatus = '';
2017-02-17 13:45:17 -03:00
$ionicHistory.nextViewOptions({
disableAnimate: true,
historyRoot: true
});
$state.go('tabs.send').then(function() {
$ionicHistory.clearHistory();
2017-02-17 13:45:17 -03:00
$state.transitionTo('tabs.home');
});
2016-10-07 20:03:51 -04:00
};
2017-06-21 13:03:48 -03:00
$scope.chooseFeeLevel = function(tx, wallet) {
if (wallet.coin == 'bch') return;
2017-06-21 17:09:33 -03:00
var scope = $rootScope.$new(true);
scope.network = tx.network;
scope.feeLevel = tx.feeLevel;
scope.noSave = true;
2017-08-29 15:47:39 -03:00
scope.coin = wallet.coin;
2017-07-10 14:19:38 -03:00
if (usingCustomFee) {
scope.customFeePerKB = tx.feeRate;
2017-07-18 11:45:30 -03:00
scope.feePerSatByte = tx.feeRate / 1000;
2017-07-10 14:19:38 -03:00
}
2017-06-21 17:09:33 -03:00
$ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', {
2017-06-21 17:09:33 -03:00
scope: scope,
2017-07-07 10:26:31 -03:00
backdropClickToClose: false,
hardwareBackButtonClose: false
}).then(function(modal) {
2017-06-21 17:09:33 -03:00
scope.chooseFeeLevelModal = modal;
scope.openModal();
});
2017-06-21 17:09:33 -03:00
scope.openModal = function() {
scope.chooseFeeLevelModal.show();
};
2017-06-21 17:09:33 -03:00
2017-07-10 14:19:38 -03:00
scope.hideModal = function(newFeeLevel, customFeePerKB) {
2017-06-23 10:24:14 -03:00
scope.chooseFeeLevelModal.hide();
2017-07-07 10:26:31 -03:00
$log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel);
2017-07-10 14:19:38 -03:00
usingCustomFee = newFeeLevel == 'custom' ? true : false;
if (tx.feeLevel == newFeeLevel && !usingCustomFee) return;
2017-07-07 10:26:31 -03:00
tx.feeLevel = newFeeLevel;
2017-07-10 14:19:38 -03:00
if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB);
2017-06-21 13:03:48 -03:00
updateTx(tx, wallet, {
clearCache: true,
2017-07-07 10:26:31 -03:00
dryRun: true
}, function() {});
};
2017-05-16 14:21:33 -03:00
};
2016-08-16 18:38:18 -03:00
});