From 3fca4b90d387435ee10ca645861f647716311efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Fri, 7 Jul 2017 10:26:31 -0300 Subject: [PATCH 1/6] custom fee feature --- src/js/controllers/confirm.js | 31 ++++++++------- src/js/controllers/preferencesFee.js | 57 +++++++++++++++++++++++----- src/js/services/feeService.js | 6 ++- src/sass/views/tab-settings.scss | 7 ++++ www/views/modals/chooseFeeLevel.html | 27 ++++++++----- www/views/preferencesFee.html | 2 +- 6 files changed, 97 insertions(+), 33 deletions(-) diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 2e408d123..3cc2af5aa 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -202,7 +202,9 @@ angular.module('copayApp.controllers').controller('confirmController', function( txp.inputs = tx.sendMaxInfo.inputs; txp.fee = tx.sendMaxInfo.fee; } else { - txp.feeLevel = tx.feeLevel; + if (tx.feeLevel == 'custom') { + txp.feePerKb = tx.feeRate; + } else txp.feeLevel = tx.feeLevel; } txp.message = tx.description; @@ -245,12 +247,12 @@ angular.module('copayApp.controllers').controller('confirmController', function( refresh(); // End of quick refresh, before wallet is selected. - if (!wallet)return cb(); + if (!wallet) return cb(); feeService.getFeeRate(tx.network, tx.feeLevel, function(err, feeRate) { if (err) return cb(err); - tx.feeRate = feeRate; + if (tx.feeLevel != 'custom') tx.feeRate = feeRate; tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; if (!wallet) @@ -294,8 +296,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( var per = (txp.fee / (txp.amount + txp.fee) * 100); txp.feeRatePerStr = per.toFixed(2) + '%'; - txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PER; - + txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PER; tx.txp[wallet.id] = txp; $log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx); @@ -558,9 +559,12 @@ angular.module('copayApp.controllers').controller('confirmController', function( scope.network = tx.network; scope.feeLevel = tx.feeLevel; scope.noSave = true; + if (tx.feeLevel == 'custom') scope.feePerSatByte = (tx.feeRate / 1000).toFixed(); $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { scope: scope, + backdropClickToClose: false, + hardwareBackButtonClose: false }).then(function(modal) { scope.chooseFeeLevelModal = modal; scope.openModal(); @@ -569,18 +573,19 @@ angular.module('copayApp.controllers').controller('confirmController', function( scope.chooseFeeLevelModal.show(); }; - scope.hideModal = function(customFeeLevel) { + scope.hideModal = function(newFeeLevel, customFeePerKBValue) { scope.chooseFeeLevelModal.hide(); - $log.debug('Custom fee level choosen:' + customFeeLevel + ' was:' + tx.feeLevel); - if (tx.feeLevel == customFeeLevel) - return; + $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); + + if (tx.feeLevel == newFeeLevel && !customFeePerKBValue) return; + + tx.feeLevel = newFeeLevel; + if (customFeePerKBValue) tx.feeRate = parseInt(customFeePerKBValue); - tx.feeLevel = customFeeLevel; updateTx(tx, wallet, { clearCache: true, - dryRun: true, - }, function() { - }); + dryRun: true + }, function() {}); }; }; diff --git a/src/js/controllers/preferencesFee.js b/src/js/controllers/preferencesFee.js index 3c3c6ce78..ffc942f1a 100644 --- a/src/js/controllers/preferencesFee.js +++ b/src/js/controllers/preferencesFee.js @@ -2,14 +2,14 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', function($scope, $timeout, $ionicHistory, lodash, gettextCatalog, configService, feeService, ongoingProcess, popupService) { - var network; - $scope.save = function(newFee) { - $scope.currentFeeLevel = newFee; - updateCurrentValues(); - if ($scope.noSave) - return; + $scope.currentFeeLevel = newFee; + + if ($scope.currentFeeLevel != 'custom') updateCurrentValues(); + else showCustomFeePrompt(); + + if ($scope.noSave) return; var opts = { wallet: { @@ -32,7 +32,6 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu }); $scope.init = function() { - $scope.network = $scope.network || 'livenet'; $scope.feeOpts = feeService.feeOpts; $scope.currentFeeLevel = $scope.feeLevel || feeService.getCurrentFeeLevel(); @@ -60,16 +59,56 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu }); if (lodash.isEmpty(value)) { - $scope.feePerSatByte = null; + $scope.feePerSatByte = $scope.currentFeeLevel == 'custom' ? $scope.feePerSatByte : null; $scope.avgConfirmationTime = null; + setMinWarning(); + setMaxWarning(); return; } $scope.feePerSatByte = (value.feePerKB / 1000).toFixed(); $scope.avgConfirmationTime = value.nbBlocks * 10; + $scope.invalidCustomFeeEntered = false; + setMinWarning(); + setMaxWarning(); }; $scope.chooseNewFee = function() { - $scope.hideModal($scope.currentFeeLevel); + $scope.hideModal($scope.currentFeeLevel, $scope.customFeePerKB); }; + + var showCustomFeePrompt = function() { + $scope.invalidCustomFeeEntered = true; + $scope.showMaxWarning = false; + popupService.showPrompt(null, gettextCatalog.getString('Custom Fee'), null, function(text) { + if (!text || !parseInt(text)) return; + $scope.feePerSatByte = parseInt(text); + $scope.customFeePerKB = ($scope.feePerSatByte * 1000).toFixed(); + setMaxWarning(); + setMinWarning(); + }); + }; + + $scope.getMinimumRecommeded = function() { + var value = lodash.find($scope.feeLevels[$scope.network], { + level: 'superEconomy' + }); + return parseInt((value.feePerKB / 1000).toFixed()); + }; + + var setMinWarning = function() { + if (parseInt($scope.feePerSatByte) < $scope.getMinimumRecommeded()) $scope.showMinWarning = true; + else $scope.showMinWarning = false; + }; + + var setMaxWarning = function() { + if (parseInt($scope.feePerSatByte) > 1000) { + $scope.showMaxWarning = true; + $scope.invalidCustomFeeEntered = true; + } else { + $scope.showMaxWarning = false; + $scope.invalidCustomFeeEntered = false; + } + }; + }); diff --git a/src/js/services/feeService.js b/src/js/services/feeService.js index cdab6a7a5..3a289bfd8 100644 --- a/src/js/services/feeService.js +++ b/src/js/services/feeService.js @@ -11,7 +11,8 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou priority: gettext('Priority'), normal: gettext('Normal'), economy: gettext('Economy'), - superEconomy: gettext('Super Economy') + superEconomy: gettext('Super Economy'), + custom: gettext('Custom') }; var cache = { @@ -24,6 +25,9 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou root.getFeeRate = function(network, feeLevel, cb) { + + if (feeLevel == 'custom') return cb(); + network = network || 'livenet'; root.getFeeLevels(function(err, levels, fromCache) { diff --git a/src/sass/views/tab-settings.scss b/src/sass/views/tab-settings.scss index 2cf1d9efa..59865d00b 100644 --- a/src/sass/views/tab-settings.scss +++ b/src/sass/views/tab-settings.scss @@ -25,6 +25,12 @@ background-color: #fff; font-size:0.9em; color: $v-mid-gray; + .text { + padding-left: 30px; + } + .icon { + position: absolute; + } } &-explanation, &-button-group { padding: 0 1rem; @@ -162,6 +168,7 @@ #settings-fee { .estimates { + min-height: 6rem; font-size: 15px; color: $v-dark-gray; margin-bottom: .5rem; diff --git a/www/views/modals/chooseFeeLevel.html b/www/views/modals/chooseFeeLevel.html index 1d65c73f8..542cc223b 100644 --- a/www/views/modals/chooseFeeLevel.html +++ b/www/views/modals/chooseFeeLevel.html @@ -1,26 +1,27 @@ - +
{{'Bitcoin Network Fee Policy'|translate}}
-
- +
Average confirmation time: - {{avgConfirmationTime | amDurationFormat: 'minute'}} - ... + {{avgConfirmationTime | amDurationFormat: 'minute'}} + Could not be estimated + ...
Current fee rate for this policy: - {{feePerSatByte}} satoshis/byte - ... + {{feePerSatByte}} satoshis/byte + ...
-
[{{network}}] + [{{network}}]
@@ -28,5 +29,13 @@ {{level|translate}}
+
+ + Your fee is lower than the minimum recommended ({{getMinimumRecommeded()}} satoshis/byte). Your transaction may never get confirmed. +
+
+ + Your could not set a fee higher than 1000 satoshis/byte. +
diff --git a/www/views/preferencesFee.html b/www/views/preferencesFee.html index c55cd3f01..fdf29e4cd 100644 --- a/www/views/preferencesFee.html +++ b/www/views/preferencesFee.html @@ -24,7 +24,7 @@
- + {{level|translate}}
From 33c80cc3926bb09a35262ed89e1bd762faf89da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Mon, 10 Jul 2017 11:36:57 -0300 Subject: [PATCH 2/6] fixes --- src/sass/views/tab-settings.scss | 5 ++++- www/views/modals/chooseFeeLevel.html | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sass/views/tab-settings.scss b/src/sass/views/tab-settings.scss index 59865d00b..30578066f 100644 --- a/src/sass/views/tab-settings.scss +++ b/src/sass/views/tab-settings.scss @@ -26,10 +26,13 @@ font-size:0.9em; color: $v-mid-gray; .text { - padding-left: 30px; + padding-left: 25px; } .icon { position: absolute; + img { + width: 20px; + } } } &-explanation, &-button-group { diff --git a/www/views/modals/chooseFeeLevel.html b/www/views/modals/chooseFeeLevel.html index 542cc223b..90d59169d 100644 --- a/www/views/modals/chooseFeeLevel.html +++ b/www/views/modals/chooseFeeLevel.html @@ -30,11 +30,11 @@
- + Your fee is lower than the minimum recommended ({{getMinimumRecommeded()}} satoshis/byte). Your transaction may never get confirmed.
- + Your could not set a fee higher than 1000 satoshis/byte.
From 6102423bae1dc814aaf24a3f03ce0d35efd77f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Mon, 10 Jul 2017 12:11:46 -0300 Subject: [PATCH 3/6] add title to prompt --- src/js/controllers/preferencesFee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/controllers/preferencesFee.js b/src/js/controllers/preferencesFee.js index ffc942f1a..06033967a 100644 --- a/src/js/controllers/preferencesFee.js +++ b/src/js/controllers/preferencesFee.js @@ -80,7 +80,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu var showCustomFeePrompt = function() { $scope.invalidCustomFeeEntered = true; $scope.showMaxWarning = false; - popupService.showPrompt(null, gettextCatalog.getString('Custom Fee'), null, function(text) { + popupService.showPrompt(gettextCatalog.getString('Custom Fee'), gettextCatalog.getString('Set your own fee in satoshis/byte'), null, function(text) { if (!text || !parseInt(text)) return; $scope.feePerSatByte = parseInt(text); $scope.customFeePerKB = ($scope.feePerSatByte * 1000).toFixed(); From af4c45f811ba0f14193ab4523ab5c8426fa8ecd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Mon, 10 Jul 2017 12:18:19 -0300 Subject: [PATCH 4/6] fix mobile prompt with timeout --- src/js/controllers/preferencesFee.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/js/controllers/preferencesFee.js b/src/js/controllers/preferencesFee.js index 06033967a..1811f4f32 100644 --- a/src/js/controllers/preferencesFee.js +++ b/src/js/controllers/preferencesFee.js @@ -86,6 +86,9 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu $scope.customFeePerKB = ($scope.feePerSatByte * 1000).toFixed(); setMaxWarning(); setMinWarning(); + $timeout(function() { + $scope.$apply(); + }); }); }; From 7b802b7f9af1bb0616b02a294f50d58862b3e7ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Mon, 10 Jul 2017 14:07:01 -0300 Subject: [PATCH 5/6] avoid negative fee --- src/js/controllers/preferencesFee.js | 3 ++- www/views/modals/chooseFeeLevel.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/js/controllers/preferencesFee.js b/src/js/controllers/preferencesFee.js index 1811f4f32..9339b413e 100644 --- a/src/js/controllers/preferencesFee.js +++ b/src/js/controllers/preferencesFee.js @@ -80,8 +80,9 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu var showCustomFeePrompt = function() { $scope.invalidCustomFeeEntered = true; $scope.showMaxWarning = false; + $scope.showMinWarning = false; popupService.showPrompt(gettextCatalog.getString('Custom Fee'), gettextCatalog.getString('Set your own fee in satoshis/byte'), null, function(text) { - if (!text || !parseInt(text)) return; + if (!text || !parseInt(text) || parseInt(text) <= 0) return; $scope.feePerSatByte = parseInt(text); $scope.customFeePerKB = ($scope.feePerSatByte * 1000).toFixed(); setMaxWarning(); diff --git a/www/views/modals/chooseFeeLevel.html b/www/views/modals/chooseFeeLevel.html index 90d59169d..c651b146d 100644 --- a/www/views/modals/chooseFeeLevel.html +++ b/www/views/modals/chooseFeeLevel.html @@ -31,7 +31,7 @@
- Your fee is lower than the minimum recommended ({{getMinimumRecommeded()}} satoshis/byte). Your transaction may never get confirmed. + Your fee is lower than the recommended super economy fee ({{getMinimumRecommeded()}} satoshis/byte). Your transaction may never get confirmed.
From 3f27c3d2313841c2b10835f60f77ae71322a0a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Baz=C3=A1n?= Date: Mon, 10 Jul 2017 14:19:38 -0300 Subject: [PATCH 6/6] code refactor --- src/js/controllers/confirm.js | 21 +++++++++++++++------ www/views/modals/chooseFeeLevel.html | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 3cc2af5aa..f688ed3fc 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -22,6 +22,9 @@ angular.module('copayApp.controllers').controller('confirmController', function( var isCordova = platformInfo.isCordova; var isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; + //custom fee flag + var usingCustomFee = null; + function refresh() { $timeout(function() { $scope.$apply(); @@ -202,7 +205,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( txp.inputs = tx.sendMaxInfo.inputs; txp.fee = tx.sendMaxInfo.fee; } else { - if (tx.feeLevel == 'custom') { + if (usingCustomFee) { txp.feePerKb = tx.feeRate; } else txp.feeLevel = tx.feeLevel; } @@ -252,7 +255,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( feeService.getFeeRate(tx.network, tx.feeLevel, function(err, feeRate) { if (err) return cb(err); - if (tx.feeLevel != 'custom') tx.feeRate = feeRate; + if (!usingCustomFee) tx.feeRate = feeRate; tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; if (!wallet) @@ -559,7 +562,11 @@ angular.module('copayApp.controllers').controller('confirmController', function( scope.network = tx.network; scope.feeLevel = tx.feeLevel; scope.noSave = true; - if (tx.feeLevel == 'custom') scope.feePerSatByte = (tx.feeRate / 1000).toFixed(); + + if (usingCustomFee) { + scope.customFeePerKB = tx.feeRate; + scope.feePerSatByte = (tx.feeRate / 1000).toFixed(); + } $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { scope: scope, @@ -573,14 +580,16 @@ angular.module('copayApp.controllers').controller('confirmController', function( scope.chooseFeeLevelModal.show(); }; - scope.hideModal = function(newFeeLevel, customFeePerKBValue) { + scope.hideModal = function(newFeeLevel, customFeePerKB) { scope.chooseFeeLevelModal.hide(); $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); - if (tx.feeLevel == newFeeLevel && !customFeePerKBValue) return; + usingCustomFee = newFeeLevel == 'custom' ? true : false; + + if (tx.feeLevel == newFeeLevel && !usingCustomFee) return; tx.feeLevel = newFeeLevel; - if (customFeePerKBValue) tx.feeRate = parseInt(customFeePerKBValue); + if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB); updateTx(tx, wallet, { clearCache: true, diff --git a/www/views/modals/chooseFeeLevel.html b/www/views/modals/chooseFeeLevel.html index c651b146d..ba2aa85a4 100644 --- a/www/views/modals/chooseFeeLevel.html +++ b/www/views/modals/chooseFeeLevel.html @@ -13,12 +13,12 @@
Average confirmation time: {{avgConfirmationTime | amDurationFormat: 'minute'}} - Could not be estimated + Could not be estimated ...
Current fee rate for this policy: - {{feePerSatByte}} satoshis/byte + {{feePerSatByte}} satoshis/byte ...
[{{network}}]