add low amount in txhistory/details and balance
This commit is contained in:
parent
fdf73fa838
commit
b83c0590dc
6 changed files with 104 additions and 52 deletions
|
|
@ -47,6 +47,19 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
$scope.txps = lodash.sortBy(txps, 'createdOn').reverse();
|
$scope.txps = lodash.sortBy(txps, 'createdOn').reverse();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var analyzeUtxosDone;
|
||||||
|
|
||||||
|
var analyzeUtxos = function() {
|
||||||
|
if (analyzeUtxosDone) return;
|
||||||
|
|
||||||
|
feeService.getFeeLevels(function(err, levels){
|
||||||
|
walletService.getLowUtxos($scope.wallet, levels, function(err, resp){
|
||||||
|
analyzeUtxosDone = true;
|
||||||
|
$scope.lowUtxosWarning = resp.warning;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var updateStatus = function(force) {
|
var updateStatus = function(force) {
|
||||||
$scope.updatingStatus = true;
|
$scope.updatingStatus = true;
|
||||||
$scope.updateStatusError = null;
|
$scope.updateStatusError = null;
|
||||||
|
|
@ -72,6 +85,8 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
analyzeUtxos();
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -154,10 +169,10 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
feeService.getLowAmount($scope.wallet, function(err, lowAmount){
|
feeService.getFeeLevels(function(err, levels){
|
||||||
walletService.getTxHistory($scope.wallet, {
|
walletService.getTxHistory($scope.wallet, {
|
||||||
progressFn: progressFn,
|
progressFn: progressFn,
|
||||||
lowAmount: lowAmount,
|
feeLevels: levels,
|
||||||
}, function(err, txHistory) {
|
}, function(err, txHistory) {
|
||||||
$scope.updatingTxHistory = false;
|
$scope.updatingTxHistory = false;
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
||||||
var root = {};
|
var root = {};
|
||||||
|
|
||||||
var CACHE_TIME_TS = 60; // 1 min
|
var CACHE_TIME_TS = 60; // 1 min
|
||||||
var LOW_AMOUNT_RATIO = 0.15; //Ratio low amount warning (econ fee/amount)
|
|
||||||
|
|
||||||
// Constant fee options to translate
|
// Constant fee options to translate
|
||||||
root.feeOpts = {
|
root.feeOpts = {
|
||||||
|
|
@ -83,51 +82,5 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// These 2 functions were taken from
|
|
||||||
// https://github.com/bitpay/bitcore-wallet-service/blob/master/lib/model/txproposal.js#L243
|
|
||||||
|
|
||||||
function getEstimatedSizeForSingleInput(wallet) {
|
|
||||||
switch (wallet.credentials.addressType) {
|
|
||||||
case 'P2PKH':
|
|
||||||
return 147;
|
|
||||||
default:
|
|
||||||
case 'P2SH':
|
|
||||||
return wallet.m * 72 + wallet.n * 36 + 44;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function getEstimatedSize(wallet) {
|
|
||||||
// Note: found empirically based on all multisig P2SH inputs and within m & n allowed limits.
|
|
||||||
var safetyMargin = 0.02;
|
|
||||||
|
|
||||||
var overhead = 4 + 4 + 9 + 9;
|
|
||||||
var inputSize = getEstimatedSizeForSingleInput(wallet);
|
|
||||||
var outputSize = 34;
|
|
||||||
var nbInputs = 1; //Assume 1 input
|
|
||||||
var nbOutputs = 2; // Assume 2 outputs
|
|
||||||
|
|
||||||
var size = overhead + inputSize * nbInputs + outputSize * nbOutputs;
|
|
||||||
return parseInt((size * (1 + safetyMargin)).toFixed(0));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Approx utxo amount, from which the uxto is economically redeemable
|
|
||||||
root.getLowAmount = function(wallet, cb) {
|
|
||||||
root.getFeeLevels(function(err, levels) {
|
|
||||||
if (err) return cb(err);
|
|
||||||
|
|
||||||
var lowLevelRate = (lodash.find(levels[wallet.network], {
|
|
||||||
level: 'economy',
|
|
||||||
}).feePerKB / 1000).toFixed(0);
|
|
||||||
|
|
||||||
var size = getEstimatedSize(wallet);
|
|
||||||
|
|
||||||
var minFee = size * lowLevelRate;
|
|
||||||
|
|
||||||
return cb(null, parseInt(minFee / (LOW_AMOUNT_RATIO)));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,6 @@ angular.module('copayApp.services')
|
||||||
wallet.m = wallet.credentials.m;
|
wallet.m = wallet.credentials.m;
|
||||||
wallet.n = wallet.credentials.n;
|
wallet.n = wallet.credentials.n;
|
||||||
|
|
||||||
wallet.lowAmount =
|
|
||||||
|
|
||||||
root.updateWalletSettings(wallet);
|
root.updateWalletSettings(wallet);
|
||||||
root.wallet[walletId] = wallet;
|
root.wallet[walletId] = wallet;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, intelTEE, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txFormatService, $ionicModal, $state, bwcService, bitcore, popupService) {
|
angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, intelTEE, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txFormatService, $ionicModal, $state, bwcService, bitcore, popupService) {
|
||||||
// `wallet` is a decorated version of client.
|
// `wallet` is a decorated version of client.
|
||||||
|
|
||||||
|
var LOW_AMOUNT_RATIO = 0.15; //Ratio low amount warning (econ fee/amount)
|
||||||
|
var TOTAL_LOW_WARNING_RATIO = .15;
|
||||||
|
|
||||||
var root = {};
|
var root = {};
|
||||||
|
|
||||||
root.externalSource = {
|
root.externalSource = {
|
||||||
|
|
@ -401,6 +404,11 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
var progressFn = opts.progressFn || function() {};
|
var progressFn = opts.progressFn || function() {};
|
||||||
var foundLimitTx = false;
|
var foundLimitTx = false;
|
||||||
|
|
||||||
|
|
||||||
|
if (opts.feeLevels) {
|
||||||
|
opts.lowAmount = root.getLowAmount(wallet, opts.feeLevels);
|
||||||
|
}
|
||||||
|
|
||||||
var fixTxsUnit = function(txs) {
|
var fixTxsUnit = function(txs) {
|
||||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||||
|
|
||||||
|
|
@ -512,6 +520,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
function updateLowAmount(txs) {
|
function updateLowAmount(txs) {
|
||||||
if (!opts.lowAmount) return;
|
if (!opts.lowAmount) return;
|
||||||
|
|
||||||
lodash.each(txs, function(tx) {
|
lodash.each(txs, function(tx) {
|
||||||
tx.lowAmount = tx.amount < opts.lowAmount;
|
tx.lowAmount = tx.amount < opts.lowAmount;
|
||||||
});
|
});
|
||||||
|
|
@ -881,6 +890,76 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// These 2 functions were taken from
|
||||||
|
// https://github.com/bitpay/bitcore-wallet-service/blob/master/lib/model/txproposal.js#L243
|
||||||
|
|
||||||
|
function getEstimatedSizeForSingleInput(wallet) {
|
||||||
|
switch (wallet.credentials.addressType) {
|
||||||
|
case 'P2PKH':
|
||||||
|
return 147;
|
||||||
|
default:
|
||||||
|
case 'P2SH':
|
||||||
|
return wallet.m * 72 + wallet.n * 36 + 44;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
root.getEstimatedTxSize = function(wallet, nbOutputs) {
|
||||||
|
// Note: found empirically based on all multisig P2SH inputs and within m & n allowed limits.
|
||||||
|
var safetyMargin = 0.02;
|
||||||
|
|
||||||
|
var overhead = 4 + 4 + 9 + 9;
|
||||||
|
var inputSize = getEstimatedSizeForSingleInput(wallet);
|
||||||
|
var outputSize = 34;
|
||||||
|
var nbInputs = 1; //Assume 1 input
|
||||||
|
var nbOutputs = nbOutputs || 2; // Assume 2 outputs
|
||||||
|
|
||||||
|
var size = overhead + inputSize * nbInputs + outputSize * nbOutputs;
|
||||||
|
return parseInt((size * (1 + safetyMargin)).toFixed(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Approx utxo amount, from which the uxto is economically redeemable
|
||||||
|
root.getLowAmount = function(wallet, feeLevels, nbOutputs) {
|
||||||
|
var lowLevelRate = (lodash.find(feeLevels[wallet.network], {
|
||||||
|
level: 'normal',
|
||||||
|
}).feePerKB / 1000).toFixed(0);
|
||||||
|
|
||||||
|
var size = root.getEstimatedTxSize(wallet, nbOutputs);
|
||||||
|
var minFee = size * lowLevelRate;
|
||||||
|
|
||||||
|
return parseInt(minFee / (LOW_AMOUNT_RATIO));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
root.getLowUtxos = function(wallet, levels, cb) {
|
||||||
|
|
||||||
|
wallet.getUtxos({}, function(err, resp) {
|
||||||
|
if (err || !resp || !resp.length) return cb();
|
||||||
|
|
||||||
|
|
||||||
|
var lowAmountN = root.getLowAmount(wallet, levels, resp.length + 1);
|
||||||
|
console.log('[walletService.js.946:lowAmountN:]',lowAmountN); //TODO
|
||||||
|
var total = lodash.sum(resp, 'satoshis');
|
||||||
|
console.log('[walletService.js.948:total:]',total); //TODO
|
||||||
|
|
||||||
|
var lowAmount1 = root.getLowAmount(wallet, levels);
|
||||||
|
console.log('[walletService.js.950:lowAmount1:]',lowAmount1); //TODO
|
||||||
|
var lowUtxos = lodash.filter(resp, function(x) {
|
||||||
|
return x.satoshis < lowAmount1;
|
||||||
|
});
|
||||||
|
|
||||||
|
var totalLow = lodash.sum(lowUtxos, 'satoshis');
|
||||||
|
|
||||||
|
return cb(err, {
|
||||||
|
lowUtxos: lowUtxos,
|
||||||
|
warning: lowAmountN / total > TOTAL_LOW_WARNING_RATIO,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
root.getAddress = function(wallet, forceNew, cb) {
|
root.getAddress = function(wallet, forceNew, cb) {
|
||||||
storageService.getLastAddress(wallet.id, function(err, addr) {
|
storageService.getLastAddress(wallet.id, function(err, addr) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="item low-fees" ng-if="btx.lowAmount">
|
<div class="item low-fees" ng-if="btx.lowAmount">
|
||||||
<i class="icon"><img src="img/icon-warning.png" width="20px"></i>
|
<i class="icon"><img src="img/icon-warning.png" width="20px"></i>
|
||||||
<span translate>This transaction amount is too small given current Bitcoin network fees. Spending these funds will incur in fees comparable to the amount itself. </span>
|
<span translate>
|
||||||
|
This transaction amount is too small compared to current Bitcoin network fees. Spending these funds will need a Bitcoin network fee cost comparable to the funds itself. </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item single-line">
|
<div class="item single-line">
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,12 @@
|
||||||
Wallet not backed up
|
Wallet not backed up
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="wallet-not-backed-up-warning" ng-if="lowUtxosWarning" ui-sref="tabs.settings.addresses({walletId:wallet.id,from: 'tabs.wallet'})" translate>
|
||||||
|
Spending this balance will need significant Bitcoin network fees
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<div class="p60b" ng-if="wallet && wallet.isComplete() && !walletNotRegistered" style="padding-top: 1rem;">
|
<div class="p60b" ng-if="wallet && wallet.isComplete() && !walletNotRegistered" style="padding-top: 1rem;">
|
||||||
<div class="oh pr m20t" ng-show="wallet.incorrectDerivation">
|
<div class="oh pr m20t" ng-show="wallet.incorrectDerivation">
|
||||||
<div class="text-center text-warning">
|
<div class="text-center text-warning">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue