send working. SendMax / PayPro: todo

This commit is contained in:
Matias Alejo Garcia 2017-06-21 13:03:48 -03:00
parent 9b90b8f2aa
commit 442e64c20c
No known key found for this signature in database
GPG Key ID: 02470DB551277AB3
3 changed files with 114 additions and 98 deletions

View File

@ -3,6 +3,7 @@
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError) { angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError) {
var countDown = null; var countDown = null;
var CONFIRM_LIMIT_USD = 20;
var tx = {}; var tx = {};
@ -66,7 +67,6 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if (!status.availableBalanceSat) if (!status.availableBalanceSat)
$log.debug('No balance available in: ' + w.name); $log.debug('No balance available in: ' + w.name);
console.log('[confirm.js.68]', status.availableBalanceSat, minAmount); //TODO
if (status.availableBalanceSat > minAmount) { if (status.availableBalanceSat > minAmount) {
filteredWallets.push(w); filteredWallets.push(w);
} }
@ -106,6 +106,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
toEmail: data.stateParams.toEmail, toEmail: data.stateParams.toEmail,
toColor: data.stateParams.toColor, toColor: data.stateParams.toColor,
network: (new bitcore.Address(data.stateParams.toAddress)).network.name, network: (new bitcore.Address(data.stateParams.toAddress)).network.name,
txp: {},
}; };
@ -212,20 +213,28 @@ angular.module('copayApp.controllers').controller('confirmController', function(
}); });
}; };
function updateTx(tx, wallet, opts, cb) {
if (opts.clearCache) {
function updateTx(tx, wallet, cb) { tx.txp = {};
}
// Amount
tx.amountStr = txFormatService.formatAmountStr(tx.amount);
tx.amountValueStr = $scope.amountStr.split(' ')[0];
tx.amountUnitStr = $scope.amountStr.split(' ')[1];
txFormatService.formatAlternativeStr(tx.amount, function(v) {
tx.alternativeAmountStr = v;
});
$scope.tx = tx; $scope.tx = tx;
// Amount
tx.amountStr = txFormatService.formatAmountStr(tx.toAmount);
console.log('[confirm.js.217:tx:]', tx); //TODO
tx.amountValueStr = tx.amountStr.split(' ')[0];
tx.amountUnitStr = tx.amountStr.split(' ')[1];
txFormatService.formatAlternativeStr(tx.toAmount, function(v) {
tx.alternativeAmountStr = v;
});
// inmediate refresh of know values
$timeout(function() {
$scope.$apply();
}, 1);
feeService.getFeeRate(tx.network, tx.feeLevel, function(err, feeRate) { feeService.getFeeRate(tx.network, tx.feeLevel, function(err, feeRate) {
if (err) return cb(err); if (err) return cb(err);
@ -250,20 +259,28 @@ angular.module('copayApp.controllers').controller('confirmController', function(
tx.toAmount = parseFloat((tx.sendMaxInfo.amount * unitToSatoshi).toFixed(0)); tx.toAmount = parseFloat((tx.sendMaxInfo.amount * unitToSatoshi).toFixed(0));
} }
getTxp(lodash.clone(tx), wallet, true, function(err, txp) {
// txp already generated for this wallet?
if (tx.txp[wallet.id])
return cb();
getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) {
if (err) return cb(err); if (err) return cb(err);
if (tx.sendMaxInfo) if (tx.sendMaxInfo)
showSendMaxWarning(sendMaxInfo, function(err) {}); showSendMaxWarning(sendMaxInfo, function(err) {});
tx.feeStr = txFormatService.formatAmountStr(txp.fee);
txFormatService.formatAlternativeStr(txp.fee, function(v) {
tx.alternativeFeeStr = v;
});
tx.feeRateStr = (txp.fee / (txp.amount + txp.fee) * 100).toFixed(2) + '%';
tx.txp = tx.txp || []; txp.feeStr = txFormatService.formatAmountStr(txp.fee);
txFormatService.formatAlternativeStr(txp.fee, function(v) {
txp.alternativeFeeStr = v;
});
txp.feeRatePerStr = (txp.fee / (txp.amount + txp.fee) * 100).toFixed(2) + '%';
tx.txp[wallet.id] = txp; tx.txp[wallet.id] = txp;
$log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx);
return cb(); return cb();
}); });
@ -362,15 +379,14 @@ angular.module('copayApp.controllers').controller('confirmController', function(
setWallet(wallet, tx); setWallet(wallet, tx);
}; };
// TODO $scope.showDescriptionPopup = function(tx) {
$scope.showDescriptionPopup = function() {
var message = gettextCatalog.getString('Add description'); var message = gettextCatalog.getString('Add description');
var opts = { var opts = {
defaultText: $scope.description defaultText: tx.description
}; };
popupService.showPrompt(null, message, opts, function(res) { popupService.showPrompt(null, message, opts, function(res) {
if (typeof res != 'undefined') $scope.description = res; if (typeof res != 'undefined') tx.description = res;
$timeout(function() { $timeout(function() {
$scope.$apply(); $scope.$apply();
}); });
@ -421,7 +437,9 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if ($scope.paypro) if ($scope.paypro)
_paymentTimeControl($scope.paypro.expires); _paymentTimeControl($scope.paypro.expires);
updateTx(tx, wallet, function(err) { updateTx(tx, wallet, {
dryRun: true
}, function(err) {
if (err) return; if (err) return;
$timeout(function() { $timeout(function() {
@ -454,14 +472,12 @@ angular.module('copayApp.controllers').controller('confirmController', function(
$scope.payproModal.hide(); $scope.payproModal.hide();
}; };
$scope.approve = function(onSendStatusChange) { $scope.approve = function(tx, wallet, onSendStatusChange) {
var wallet = $scope.wallet; if (!tx || !wallet) return;
if (!wallet) {
return;
}
if ($scope.paypro && $scope.paymentExpired.value) { // TODO
if (tx.paypro && $scope.paymentExpired.value) {
popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.')); popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.'));
$scope.sendStatus = ''; $scope.sendStatus = '';
$timeout(function() { $timeout(function() {
@ -471,43 +487,57 @@ angular.module('copayApp.controllers').controller('confirmController', function(
} }
ongoingProcess.set('creatingTx', true, onSendStatusChange); ongoingProcess.set('creatingTx', true, onSendStatusChange);
getTxp(wallet, false, function(err, txp) { getTxp(lodash.clone(tx), wallet, false, function(err, txp) {
console.log('[confirm.js.490:txp:]',txp); //TODO
ongoingProcess.set('creatingTx', false, onSendStatusChange); ongoingProcess.set('creatingTx', false, onSendStatusChange);
if (err) return; if (err) return;
var spendingPassEnabled = walletService.isEncrypted(wallet); // confirm txs for more that 20usd, if not spending/touchid is enabled
var bigAmount = parseFloat(txFormatService.formatToUSD(txp.amount)) > 20; function confirmTx(cb) {
var message = gettextCatalog.getString('Sending {{amountStr}} from your {{name}} wallet', { if (walletService.isEncrypted(wallet))
amountStr: $scope.amountStr, return cb();
name: wallet.name
});
var okText = gettextCatalog.getString('Confirm');
var cancelText = gettextCatalog.getString('Cancel');
if (!spendingPassEnabled && !touchIdEnabled) { var amountUsd = parseFloat(txFormatService.formatToUSD(txp.amount));
if (isCordova) { if (amountUsd <= CONFIRM_LIMIT_USD)
if (bigAmount) { return cb();
popupService.showConfirm(null, message, okText, cancelText, function(ok) {
if (!ok) { var message = gettextCatalog.getString('Sending {{amountStr}} from your {{name}} wallet', {
$scope.sendStatus = ''; amountStr: tx.amountStr,
$timeout(function() { name: wallet.name
$scope.$apply(); });
}); var okText = gettextCatalog.getString('Confirm');
return; var cancelText = gettextCatalog.getString('Cancel');
} popupService.showConfirm(null, message, okText, cancelText, function(ok) {
publishAndSign(wallet, txp, onSendStatusChange); return cb(!ok);
}); });
} else publishAndSign(wallet, txp, onSendStatusChange); };
} else {
popupService.showConfirm(null, message, okText, cancelText, function(ok) { function publishAndSign() {
if (!ok) { if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
$scope.sendStatus = ''; $log.info('No signing proposal: No private key');
return;
} return walletService.onlyPublish(wallet, txp, function(err) {
publishAndSign(wallet, txp, onSendStatusChange); if (err) setSendError(err);
}); }, onSendStatusChange);
} }
} else publishAndSign(wallet, txp, onSendStatusChange);
walletService.publishAndSign(wallet, txp, function(err, txp) {
if (err) return setSendError(err);
}, onSendStatusChange);
};
confirmTx(function(nok) {
if (nok) {
$scope.sendStatus = '';
$timeout(function() {
$scope.$apply();
});
return;
}
console.log('[confirm.js.541]'); //TODO
publishAndSign();
});
}); });
}; };
@ -553,24 +583,9 @@ angular.module('copayApp.controllers').controller('confirmController', function(
}); });
}; };
function publishAndSign(wallet, txp, onSendStatusChange) { $scope.chooseFeeLevel = function(tx, wallet) {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) { $scope.customFeeLevel = tx.feeLevel;
$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);
}, onSendStatusChange);
};
$scope.chooseFeeLevel = function() {
$scope.customFeeLevel = feeLevel;
$ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', {
scope: $scope, scope: $scope,
}).then(function(modal) { }).then(function(modal) {
@ -581,16 +596,17 @@ angular.module('copayApp.controllers').controller('confirmController', function(
$scope.chooseFeeLevelModal.show(); $scope.chooseFeeLevelModal.show();
}; };
$scope.hideModal = function(customFeeLevel) { $scope.hideModal = function(customFeeLevel) {
if (customFeeLevel) { $log.debug('Custom fee level choosen:' + customFeeLevel + ' was:' + tx.feeLevel);
ongoingProcess.set('gettingFeeLevels', true); if (tx.feeLevel == customFeeLevel)
setAndShowFee(customFeeLevel, function() { $scope.chooseFeeLevelModal.hide();
ongoingProcess.set('gettingFeeLevels', false);
resetView(); tx.feeLevel = customFeeLevel;
if ($scope.wallet) updateTx(tx, wallet, {
useSelectedWallet(); clearCache: true,
}) dryRun: true,
} }, function() {
$scope.chooseFeeLevelModal.hide(); $scope.chooseFeeLevelModal.hide();
});
}; };
}; };

View File

@ -26,7 +26,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
root.getFeeRate = function(network, feeLevel, cb) { root.getFeeRate = function(network, feeLevel, cb) {
network = network || 'livenet'; network = network || 'livenet';
root.getFeeLevels(function(err, levels) { root.getFeeLevels(function(err, levels, fromCache) {
if (err) return cb(err); if (err) return cb(err);
var feeLevelRate = lodash.find(levels[network], { var feeLevelRate = lodash.find(levels[network], {
@ -42,7 +42,8 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
} }
var feeRate = feeLevelRate.feePerKB; var feeRate = feeLevelRate.feePerKB;
$log.debug('Dynamic fee: ' + feeLevel + ' ' + feeRate + ' SAT');
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network +' ' + (feeLevelRate.feePerKB / 1000).toFixed() + ' SAT/B');
return cb(null, feeRate); return cb(null, feeRate);
}); });
@ -55,9 +56,8 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
root.getFeeLevels = function(cb) { root.getFeeLevels = function(cb) {
if (cache.updateTs > Date.now() - CACHE_TIME_TS * 1000 ) { if (cache.updateTs > Date.now() - CACHE_TIME_TS * 1000 ) {
$log.debug('Fee cache hit');
$timeout( function() { $timeout( function() {
return cb(null, cache.data); return cb(null, cache.data, true);
}, 1); }, 1);
} }

View File

@ -77,15 +77,15 @@
</div> </div>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>
</a> </a>
<div class="item item-icon-right" ng-if="!insufficientFunds && !noMatchingWallet" ng-click="chooseFeeLevel()"> <div class="item item-icon-right" ng-if="!insufficientFunds && !noMatchingWallet" ng-click="chooseFeeLevel(tx, wallet)">
<span class="label">{{'Fee:' | translate}} {{tx.feeLevel | translate}}</span> <span class="label">{{'Fee:' | translate}} {{tx.feeLevelName | translate}}</span>
<span class="m10l">{{tx.fee || '...'}}</span> <span class="m10l">{{tx.txp[wallet.id].feeStr || '...'}}</span>
<span class="item-note m10l"> <span class="item-note m10l">
<span>{{tx.alternativeFeeStr || '...'}}&nbsp;<span class="fee-rate" ng-if="tx.feeRatePerStr" translate>- {{tx.feeRatePerStr}} of the transaction</span></span> <span>{{tx.txp[wallet.id].alternativeFeeStr || '...'}}&nbsp;<span class="fee-rate" ng-if="tx.feeRatePerStr" translate>- {{tx.txp[wallet.id].feeRatePerStr}} of the transaction</span></span>
</span> </span>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>
</div> </div>
<a class="item item-icon-right" ng-if="!insufficientFunds && !noMatchingWallet" ng-click="showDescriptionPopup()"> <a class="item item-icon-right" ng-if="!insufficientFunds && !noMatchingWallet" ng-click="showDescriptionPopup(tx)">
<span class="label" translate>Add Memo</span> <span class="label" translate>Add Memo</span>
<span class="item-note m10l"> <span class="item-note m10l">
{{tx.description}} {{tx.description}}
@ -102,7 +102,7 @@
</div> </div>
</ion-content> </ion-content>
<click-to-accept <click-to-accept
ng-click="approve(statusChangeHandler)" ng-click="approve(tx, wallet, statusChangeHandler)"
ng-if="!isCordova" ng-if="!isCordova"
click-send-status="sendStatus" click-send-status="sendStatus"
has-wallet-chosen="wallet" has-wallet-chosen="wallet"