Merge pull request #307 from Bitcoin-com/wallet/task/518
518 - Add true pagination to the Wallet Detail screens
This commit is contained in:
commit
46b5317f5e
6 changed files with 506 additions and 100 deletions
|
|
@ -1,16 +1,52 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService, sendFlowService, storageService, $ionicScrollDelegate, $window, bwcError, gettextCatalog, timeService, feeService, appConfigService, rateService) {
|
||||
|
||||
var HISTORY_SHOW_LIMIT = 10;
|
||||
var currentTxHistoryPage = 0;
|
||||
angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService, sendFlowService, storageService, $ionicScrollDelegate, $window, bwcError, gettextCatalog, timeService, feeService, appConfigService, rateService, walletHistoryService) {
|
||||
// Desktop can display 13 rows of transactions, bump it up to a nice round 15.
|
||||
var DISPLAY_PAGE_SIZE = 15;
|
||||
var currentTxHistoryDisplayPage = 0;
|
||||
var completeTxHistory = []
|
||||
var listeners = [];
|
||||
$scope.txps = [];
|
||||
$scope.completeTxHistory = [];
|
||||
$scope.openTxpModal = txpModalService.open;
|
||||
|
||||
// For gradual migration for doing it properly
|
||||
$scope.vm = {
|
||||
allowInfiniteScroll: false,
|
||||
gettingCachedHistory: true,
|
||||
gettingInitialHistory: true,
|
||||
updatingTxHistory: false,
|
||||
fetchedAllTxHistory: false,
|
||||
//updateTxHistoryError: false
|
||||
updateTxHistoryFailed: false
|
||||
};
|
||||
|
||||
// Need flag for when to allow infinite scroll at bottom
|
||||
// - ie not when loading initial data and there is no more cached data
|
||||
|
||||
$scope.amountIsCollapsible = false;
|
||||
$scope.color = '#888888';
|
||||
|
||||
$scope.filteredTxHistory = [];
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.isAndroid = platformInfo.isAndroid;
|
||||
$scope.isIOS = platformInfo.isIOS;
|
||||
$scope.isSearching = false;
|
||||
$scope.openTxpModal = txpModalService.open;
|
||||
$scope.requiresMultipleSignatures = false;
|
||||
$scope.showBalanceButton = false;
|
||||
$scope.status = null;
|
||||
// Displaying 50 transactions when entering the screen takes a while, so only display a subset
|
||||
// of everything we have, not the complete history.
|
||||
$scope.txHistory = []; // This is what is displayed
|
||||
$scope.txHistorySearchResults = [];
|
||||
$scope.txps = [];
|
||||
$scope.updatingStatus = false;
|
||||
$scope.updateStatusError = null;
|
||||
$scope.updatingTxHistoryProgress = 0;
|
||||
$scope.wallet = null;
|
||||
$scope.walletId = '';
|
||||
$scope.walletNotRegistered = false;
|
||||
|
||||
|
||||
|
||||
|
||||
var channel = "ga";
|
||||
if (platformInfo.isCordova) {
|
||||
|
|
@ -50,6 +86,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
$scope.updatingStatus = true;
|
||||
$scope.updateStatusError = null;
|
||||
$scope.walletNotRegistered = false;
|
||||
$scope.vm.fetchedAllTxHistory = false;
|
||||
|
||||
walletService.getStatus($scope.wallet, {
|
||||
force: !!force,
|
||||
|
|
@ -133,68 +170,96 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
if (err) return;
|
||||
$timeout(function() {
|
||||
walletService.startScan($scope.wallet, function() {
|
||||
$scope.updateAll();
|
||||
$scope.updateAll(true, true);
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var updateTxHistory = function(cb) {
|
||||
if (!cb) cb = function() {};
|
||||
$scope.updateTxHistoryError = false;
|
||||
$scope.updatingTxHistoryProgress = 0;
|
||||
|
||||
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
|
||||
walletService.getTxHistory($scope.wallet, {
|
||||
feeLevels: levels
|
||||
}, function(err, txHistory) {
|
||||
$scope.updatingTxHistory = false;
|
||||
if (err) {
|
||||
$scope.txHistory = null;
|
||||
$scope.updateTxHistoryError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
applyCurrencyAliases(txHistory);
|
||||
|
||||
var config = configService.getSync();
|
||||
var fiatCode = config.wallet.settings.alternativeIsoCode;
|
||||
lodash.each(txHistory, function(t) {
|
||||
var r = rateService.toFiat(t.amount, fiatCode, $scope.wallet.coin);
|
||||
t.alternativeAmountStr = r.toFixed(2) + ' ' + fiatCode;
|
||||
});
|
||||
|
||||
$scope.completeTxHistory = txHistory;
|
||||
|
||||
$scope.showHistory();
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
return cb();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function applyCurrencyAliases(txHistory) {
|
||||
var defaults = configService.getDefaults();
|
||||
var configCache = configService.getSync();
|
||||
|
||||
lodash.each(txHistory, function(t) {
|
||||
t.amountUnitStr = $scope.wallet.coin == 'btc'
|
||||
lodash.each(txHistory, function onTx(tx) {
|
||||
tx.amountUnitStr = $scope.wallet.coin == 'btc'
|
||||
? (configCache.bitcoinAlias || defaults.bitcoinAlias)
|
||||
: (configCache.bitcoinCashAlias || defaults.bitcoinCashAlias);
|
||||
|
||||
t.amountUnitStr = t.amountUnitStr.toUpperCase();
|
||||
tx.amountUnitStr = tx.amountUnitStr.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.showHistory = function() {
|
||||
if ($scope.completeTxHistory) {
|
||||
$scope.txHistory = $scope.completeTxHistory.slice(0, (currentTxHistoryPage + 1) * HISTORY_SHOW_LIMIT);
|
||||
$scope.txHistoryShowMore = $scope.completeTxHistory.length > $scope.txHistory.length;
|
||||
function formatTxHistoryForDisplay(txHistory) {
|
||||
applyCurrencyAliases(txHistory);
|
||||
|
||||
var config = configService.getSync();
|
||||
var fiatCode = config.wallet.settings.alternativeIsoCode;
|
||||
lodash.each(txHistory, function(t) {
|
||||
var r = rateService.toFiat(t.amount, fiatCode, $scope.wallet.coin);
|
||||
t.alternativeAmountStr = r.toFixed(2) + ' ' + fiatCode;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updateTxHistoryFromCachedData() {
|
||||
walletHistoryService.getCachedTxHistory($scope.wallet.id, function onGetCachedTxHistory(err, txHistory){
|
||||
$scope.vm.gettingCachedHistory = false;
|
||||
if (err) {
|
||||
// Don't display an error because we are also requesting the history.
|
||||
$log.error('Error getting cached tx history.', err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!txHistory) {
|
||||
$log.debug('No cached tx history.');
|
||||
return;
|
||||
}
|
||||
|
||||
formatTxHistoryForDisplay(txHistory);
|
||||
|
||||
completeTxHistory = txHistory;
|
||||
showHistory(false);
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
|
||||
function fetchAndShowTxHistory(getLatest, flushCacheOnNew) {
|
||||
$scope.vm.updatingTxHistory = true;
|
||||
|
||||
walletHistoryService.updateLocalTxHistoryByPage($scope.wallet, getLatest, flushCacheOnNew, function onUpdateLocalTxHistoryByPage(err, txHistory, fetchedAllTransactions) {
|
||||
$scope.vm.gettingInitialHistory = false;
|
||||
$scope.vm.updatingTxHistory = false;
|
||||
$scope.$broadcast('scroll.infiniteScrollComplete');
|
||||
|
||||
if (err) {
|
||||
console.error('pagination Failed to get history.', err);
|
||||
$scope.vm.updateTxHistoryFailed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fetchedAllTransactions) {
|
||||
$scope.vm.fetchedAllTxHistory = true;
|
||||
}
|
||||
|
||||
formatTxHistoryForDisplay(txHistory);
|
||||
|
||||
completeTxHistory = txHistory;
|
||||
showHistory(true);
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function showHistory(showAll) {
|
||||
if (completeTxHistory) {
|
||||
$scope.txHistory = showAll ? completeTxHistory : completeTxHistory.slice(0, (currentTxHistoryDisplayPage + 1) * DISPLAY_PAGE_SIZE);
|
||||
$scope.vm.allowInfiniteScroll = !$scope.vm.fetchedAllTxHistory && !(completeTxHistory.length === $scope.txHistory.length && $scope.vm.gettingInitialHistory);
|
||||
} else {
|
||||
$scope.vm.allowInfiniteScroll = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
$scope.getDate = function(txCreated) {
|
||||
var date = new Date(txCreated * 1000);
|
||||
|
|
@ -233,24 +298,35 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
return !tx.confirmations || tx.confirmations === 0;
|
||||
};
|
||||
|
||||
// on-infinite="showMore()"
|
||||
$scope.showMore = function() {
|
||||
$timeout(function() {
|
||||
currentTxHistoryPage++;
|
||||
$scope.showHistory();
|
||||
// Check if we have more than we are displaying
|
||||
if (completeTxHistory.length > $scope.txHistory.length) {
|
||||
currentTxHistoryDisplayPage++;
|
||||
showHistory(false);
|
||||
$scope.$broadcast('scroll.infiniteScrollComplete');
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($scope.vm.updatingTxHistory) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetchAndShowTxHistory(false, false);
|
||||
};
|
||||
|
||||
// on-refresh="onRefresh()"
|
||||
$scope.onRefresh = function() {
|
||||
$timeout(function() {
|
||||
$scope.$broadcast('scroll.refreshComplete');
|
||||
}, 300);
|
||||
$scope.updateAll(true);
|
||||
$scope.updateAll(true, false);
|
||||
};
|
||||
|
||||
$scope.updateAll = function(force, cb) {
|
||||
updateStatus(force);
|
||||
updateTxHistory(cb);
|
||||
$scope.updateAll = function(forceStatusUpdate, flushTxCacheOnNew) {
|
||||
updateStatus(forceStatusUpdate);
|
||||
//updateTxHistory(cb);
|
||||
fetchAndShowTxHistory(true, flushTxCacheOnNew);
|
||||
};
|
||||
|
||||
$scope.hideToggle = function() {
|
||||
|
|
@ -303,7 +379,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
if (!$scope.wallet) return;
|
||||
$scope.requiresMultipleSignatures = $scope.wallet.credentials.m > 1;
|
||||
|
||||
$scope.updatingTxHistory = true;
|
||||
$scope.vm.gettingInitialHistory = true;
|
||||
|
||||
addressbookService.list(function(err, ab) {
|
||||
if (err) $log.error(err);
|
||||
|
|
@ -313,11 +389,11 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
listeners = [
|
||||
$rootScope.$on('bwsEvent', function(e, walletId) {
|
||||
if (walletId == $scope.wallet.id && e.type != 'NewAddress')
|
||||
$scope.updateAll();
|
||||
$scope.updateAll(false, false);
|
||||
}),
|
||||
$rootScope.$on('Local/TxAction', function(e, walletId) {
|
||||
if (walletId == $scope.wallet.id)
|
||||
$scope.updateAll();
|
||||
$scope.updateAll(false, false);
|
||||
}),
|
||||
];
|
||||
});
|
||||
|
|
|
|||
244
src/js/services/wallet-history.service.js
Normal file
244
src/js/services/wallet-history.service.js
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
'use strict';
|
||||
|
||||
(function(){
|
||||
|
||||
angular
|
||||
.module('bitcoincom.services')
|
||||
.factory('walletHistoryService', walletHistoryService);
|
||||
|
||||
function walletHistoryService(configService, storageService, lodash, $log, txFormatService) {
|
||||
//var PAGE_SIZE = 50;
|
||||
var PAGE_SIZE = 20; // For dev only
|
||||
// How much to overlap on each end of the page, for mitigating inconsistent sort order.
|
||||
var PAGE_OVERLAP_FRACTION = 0.2;
|
||||
var PAGE_OVERLAP = Math.floor(PAGE_SIZE * PAGE_OVERLAP_FRACTION);
|
||||
// The amount of transactions in the new overlapping resultset that we already know about.
|
||||
// If we know about at least this many, then there are probably no gaps.
|
||||
var MIN_KNOWN_TX_OVERLAP = Math.floor(PAGE_OVERLAP * 0.5);
|
||||
|
||||
var SAFE_CONFIRMATIONS = 6;
|
||||
|
||||
var allTransactionsFetched = false;
|
||||
var service = {
|
||||
getCachedTxHistory: getCachedTxHistory,
|
||||
updateLocalTxHistoryByPage: updateLocalTxHistoryByPage,
|
||||
};
|
||||
return service;
|
||||
|
||||
function addEarlyTransactions(walletId, cachedTxs, newTxs) {
|
||||
|
||||
var cachedTxIds = {};
|
||||
cachedTxs.forEach(function forCachedTx(tx){
|
||||
cachedTxIds[tx.txid] = true;
|
||||
});
|
||||
|
||||
var someTransactionsWereNew = false;
|
||||
var overlappingTxsCount = 0;
|
||||
|
||||
newTxs.forEach(function forNewTx(tx){
|
||||
if (cachedTxIds[tx.txid]) {
|
||||
overlappingTxsCount++;
|
||||
} else {
|
||||
someTransactionsWereNew = true;
|
||||
cachedTxs.push(tx);
|
||||
}
|
||||
});
|
||||
|
||||
if (overlappingTxsCount >= MIN_KNOWN_TX_OVERLAP) { // We are good
|
||||
if (someTransactionsWereNew) {
|
||||
saveTxHistory(walletId, cachedTxs);
|
||||
} else if (overlappingTxsCount === newTxs.length) {
|
||||
allTransactionsFetched = true;
|
||||
}
|
||||
return cachedTxs;
|
||||
} else {
|
||||
// We might be missing some txs.
|
||||
console.error('We might be missing some txs in the history.');
|
||||
// Our history is wrong, so remove it - we could instead, try to fetch data that was not so early.
|
||||
storageService.removeTxHistory(walletId, function onRemoveTxHistory(){});
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function addLatestTransactions(walletId, cachedTxs, newTxs) {
|
||||
var cachedTxIds = {};
|
||||
cachedTxs.forEach(function forCachedTx(tx){
|
||||
cachedTxIds[tx.txid] = true;
|
||||
});
|
||||
|
||||
var someTransactionsWereNew = false;
|
||||
var overlappingTxsCount = 0;
|
||||
var uniqueNewTxs = [];
|
||||
|
||||
newTxs.forEach(function forNewTx(tx){
|
||||
if (cachedTxIds[tx.txid]) {
|
||||
overlappingTxsCount++;
|
||||
} else {
|
||||
someTransactionsWereNew = true;
|
||||
uniqueNewTxs.push(tx);
|
||||
}
|
||||
});
|
||||
|
||||
if (overlappingTxsCount >= MIN_KNOWN_TX_OVERLAP) { // We are good
|
||||
if (someTransactionsWereNew) {
|
||||
var allTxs = uniqueNewTxs.concat(cachedTxs);
|
||||
saveTxHistory(walletId, allTxs);
|
||||
return allTxs;
|
||||
} else {
|
||||
return cachedTxs;
|
||||
}
|
||||
} else {
|
||||
// We might be missing some txs.
|
||||
// Our history is wrong, so just include the latest ones
|
||||
saveTxHistory(walletId, newTxs);
|
||||
return newTxs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Only clear the cache once we have received new transactions from the server.
|
||||
/**
|
||||
* @param {function(err, txs)} cb - transactions is always an array, may be empty
|
||||
*/
|
||||
function fetchTxHistoryByPage(wallet, start, cb) {
|
||||
var skip = Math.max(0, start - PAGE_OVERLAP);
|
||||
var limit = PAGE_SIZE;
|
||||
|
||||
var opts = {
|
||||
skip: skip,
|
||||
limit: limit
|
||||
};
|
||||
wallet.getTxHistory(opts, function onTxHistory(err, txsFromServer) {
|
||||
if (err) {
|
||||
return cb(err, []);
|
||||
}
|
||||
|
||||
if (txsFromServer.length === 0) {
|
||||
return cb(null, []);
|
||||
}
|
||||
|
||||
var processedTxs = processNewTxs(wallet, txsFromServer);
|
||||
|
||||
return cb(null, processedTxs);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} walletId
|
||||
* @param {function(error, txs)} cb - txs is always an array, may be empty
|
||||
*/
|
||||
function getCachedTxHistory(walletId, cb) {
|
||||
storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){
|
||||
if (err) {
|
||||
return cb(err, []);
|
||||
}
|
||||
|
||||
if (!txHistoryString) {
|
||||
return cb(null, []);
|
||||
}
|
||||
|
||||
try {
|
||||
var txHistory = JSON.parse(txHistoryString);
|
||||
return cb(null, txHistory);
|
||||
} catch (e) {
|
||||
$log.error('Failed to parse tx history.', e);
|
||||
return cb(e, []);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function processNewTxs(wallet, txs) {
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
var txHistoryUnique = {};
|
||||
var processedTxs = [];
|
||||
wallet.hasUnsafeConfirmed = false;
|
||||
|
||||
lodash.each(txs, function(tx) {
|
||||
tx = txFormatService.processTx(wallet.coin, tx);
|
||||
|
||||
// no future transactions...
|
||||
if (tx.time > now)
|
||||
tx.time = now;
|
||||
|
||||
if (tx.confirmations >= SAFE_CONFIRMATIONS) {
|
||||
tx.safeConfirmed = SAFE_CONFIRMATIONS + '+';
|
||||
} else {
|
||||
tx.safeConfirmed = false;
|
||||
wallet.hasUnsafeConfirmed = true;
|
||||
}
|
||||
|
||||
if (tx.note) {
|
||||
delete tx.note.encryptedEditedByName;
|
||||
delete tx.note.encryptedBody;
|
||||
}
|
||||
|
||||
if (!txHistoryUnique[tx.txid]) {
|
||||
processedTxs.push(tx);
|
||||
txHistoryUnique[tx.txid] = true;
|
||||
} else {
|
||||
$log.debug('Ignoring duplicate TX in history: ' + tx.txid)
|
||||
}
|
||||
});
|
||||
|
||||
return processedTxs;
|
||||
};
|
||||
|
||||
function saveTxHistory(walletId, processedTxs) {
|
||||
storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){
|
||||
if (error) {
|
||||
$log.error('pagination Failed to save tx history.', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) {
|
||||
|
||||
if (flushCacheOnNew) {
|
||||
fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){
|
||||
if (err) {
|
||||
return cb(err, txs);
|
||||
}
|
||||
saveTxHistory(wallet.id, txs);
|
||||
return cb(null, txs);
|
||||
});
|
||||
} else {
|
||||
getCachedTxHistory(wallet.id, function onCachedHistory(err, cachedTxs){
|
||||
if (err) {
|
||||
$log.error('Failed to get cached tx history.', err);
|
||||
return cb(err, []);
|
||||
}
|
||||
|
||||
var start = getLatest ? 0 : cachedTxs.length;
|
||||
fetchTxHistoryByPage(wallet, start, function onFetchHistory(err, fetchedTxs){
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (fetchedTxs.length === 0) {
|
||||
return cb(null, cachedTxs, true /*fetchedAllTransactions*/);
|
||||
}
|
||||
|
||||
var txs = [];
|
||||
if (getLatest) {
|
||||
txs = addLatestTransactions(wallet.id, cachedTxs, fetchedTxs);
|
||||
} else {
|
||||
allTransactionsFetched = false;
|
||||
txs = addEarlyTransactions(wallet.id, cachedTxs, fetchedTxs);
|
||||
return cb(null, txs, allTransactionsFetched);
|
||||
}
|
||||
return cb(null, txs);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
})();
|
||||
|
|
@ -396,6 +396,23 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
return ret;
|
||||
};
|
||||
|
||||
var skipped = 0;
|
||||
|
||||
function fixTxsUnit(txs) {
|
||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||
|
||||
var cacheCoin = txs[0].amountStr.split(' ')[1];
|
||||
|
||||
if (cacheCoin == 'bits') {
|
||||
|
||||
$log.debug('Fixing Tx Cache Unit to: ' + wallet.coin)
|
||||
lodash.each(txs, function(tx) {
|
||||
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.amount);
|
||||
tx.feeStr = txFormatService.formatAmountStr(wallet.coin, tx.fees);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var updateLocalTxHistory = function(wallet, opts, cb) {
|
||||
var FIRST_LIMIT = 5;
|
||||
var LIMIT = 50;
|
||||
|
|
@ -406,25 +423,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
var progressFn = opts.progressFn || function() {};
|
||||
var foundLimitTx = false;
|
||||
|
||||
|
||||
if (opts.feeLevels) {
|
||||
opts.lowAmount = root.getLowAmount(wallet, opts.feeLevels);
|
||||
}
|
||||
|
||||
var fixTxsUnit = function(txs) {
|
||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||
|
||||
var cacheCoin = txs[0].amountStr.split(' ')[1];
|
||||
|
||||
if (cacheCoin == 'bits') {
|
||||
|
||||
$log.debug('Fixing Tx Cache Unit to: ' + wallet.coin)
|
||||
lodash.each(txs, function(tx) {
|
||||
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.amount);
|
||||
tx.feeStr = txFormatService.formatAmountStr(wallet.coin, tx.fees);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getSavedTxs(walletId, function(err, txsFromLocal) {
|
||||
if (err) return cb(err);
|
||||
|
|
@ -435,13 +437,14 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
var endingTxid = confirmedTxs[0] ? confirmedTxs[0].txid : null;
|
||||
var endingTs = confirmedTxs[0] ? confirmedTxs[0].time : null;
|
||||
|
||||
$log.debug('Confirmed TXs. Got:' + confirmedTxs.length + '/' + txsFromLocal.length);
|
||||
console.log('pagination Hard confirmed TXs. Got:' + confirmedTxs.length + '/' + txsFromLocal.length);
|
||||
|
||||
// First update
|
||||
progressFn(txsFromLocal, 0);
|
||||
wallet.completeHistory = txsFromLocal;
|
||||
|
||||
function getNewTxs(newTxs, skip, next) {
|
||||
console.log('pagination getNewTxs skip: ' + skip);
|
||||
getTxsFromServer(wallet, skip, endingTxid, requestLimit, function(err, res) {
|
||||
if (err) {
|
||||
$log.warn(bwcError.msg(err, 'Server Error')); //TODO
|
||||
|
|
@ -454,6 +457,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
return next(err);
|
||||
}
|
||||
|
||||
console.log('pagination Result count: ' + res.length);
|
||||
// Check if new txs are founds, if yes, lets investigate in the 50 next
|
||||
// To be sure we are not missing txs by sorting (maybe a new tx is after the "endingTxid"
|
||||
var newDiscoveredTxs = res.filter(function (x) {
|
||||
|
|
@ -462,7 +466,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
}).length == 0;
|
||||
});
|
||||
|
||||
$log.debug('Discovering TXs. Got:' + newDiscoveredTxs.length);
|
||||
console.log('pagination Discovering new TXs. Got:' + newDiscoveredTxs.length);
|
||||
|
||||
var shouldContinue = newDiscoveredTxs.length > 0;
|
||||
|
||||
|
|
@ -475,7 +479,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
skip = skip + requestLimit;
|
||||
|
||||
$log.debug('Syncing TXs. Got:' + newTxs.length + ' Skip:' + skip, ' EndingTxid:', endingTxid, ' Continue:', shouldContinue);
|
||||
console.log('pagination Syncing TXs. Got:' + newTxs.length + ' Skip:' + skip, ' EndingTxid:', endingTxid, ' Continue:', shouldContinue);
|
||||
|
||||
// TODO Dirty <HACK>
|
||||
// do not sync all history, just looking for a single TX.
|
||||
|
|
@ -492,14 +496,16 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
}
|
||||
// </HACK>
|
||||
|
||||
shouldContinue = false;
|
||||
|
||||
skipped = skip;
|
||||
|
||||
if (!shouldContinue) {
|
||||
$log.debug('Finished Sync: New / soft confirmed Txs: ' + newTxs.length);
|
||||
console.log('pagination Finished Sync: New / soft confirmed Txs: ' + newTxs.length);
|
||||
return next(null, newTxs);
|
||||
}
|
||||
|
||||
requestLimit = LIMIT;
|
||||
getNewTxs(newTxs, skip, next);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -535,6 +541,87 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
if (opts.getMoreTxs) {
|
||||
var requestLimit = LIMIT;
|
||||
getNewTxs([], skipped, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
console.log();
|
||||
createReceivedEvents(txs);
|
||||
|
||||
var newHistory = lodash.uniq(lodash.compact(txs.concat(confirmedTxs)), function(x) {
|
||||
return x.txid;
|
||||
});
|
||||
|
||||
|
||||
function updateNotes(cb2) {
|
||||
if (!endingTs) return cb2();
|
||||
|
||||
$log.debug('Syncing notes from: ' + endingTs);
|
||||
wallet.getTxNotes({
|
||||
minTs: endingTs
|
||||
}, function(err, notes) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return cb2();
|
||||
};
|
||||
lodash.each(notes, function(note) {
|
||||
$log.debug('Note for ' + note.txid);
|
||||
lodash.each(newHistory, function(tx) {
|
||||
if (tx.txid == note.txid) {
|
||||
$log.debug('...updating note for ' + note.txid);
|
||||
tx.note = note;
|
||||
}
|
||||
});
|
||||
});
|
||||
return cb2();
|
||||
});
|
||||
}
|
||||
|
||||
function updateLowAmount(txs) {
|
||||
if (!opts.lowAmount) return;
|
||||
|
||||
lodash.each(txs, function(tx) {
|
||||
tx.lowAmount = tx.amount < opts.lowAmount;
|
||||
});
|
||||
};
|
||||
|
||||
updateLowAmount(txs);
|
||||
|
||||
updateNotes(function() {
|
||||
|
||||
// <HACK>
|
||||
if (foundLimitTx) {
|
||||
$log.debug('Tx history read until limitTx: ' + opts.limitTx);
|
||||
return cb(null, newHistory);
|
||||
}
|
||||
// </HACK>
|
||||
|
||||
var historyToSave = JSON.stringify(newHistory);
|
||||
|
||||
lodash.each(txs, function(tx) {
|
||||
tx.recent = true;
|
||||
})
|
||||
|
||||
$log.debug('Tx History synced. Total Txs: ' + newHistory.length);
|
||||
|
||||
// Final update
|
||||
if (walletId == wallet.credentials.walletId) {
|
||||
wallet.completeHistory = newHistory;
|
||||
}
|
||||
|
||||
return storageService.setTxHistory(historyToSave, walletId, function() {
|
||||
$log.debug('Tx History saved.');
|
||||
return cb(null, newHistory);
|
||||
});
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
skipped = 0;
|
||||
|
||||
getNewTxs([], 0, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
|
@ -603,14 +690,19 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
return storageService.setTxHistory(historyToSave, walletId, function() {
|
||||
$log.debug('Tx History saved.');
|
||||
|
||||
return cb();
|
||||
return cb(null, newHistory);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
root.getMoreTxs = function(wallet, cb) {
|
||||
var opts = {};
|
||||
opts.getMoreTxs = true;
|
||||
updateLocalTxHistory(wallet, opts, cb);
|
||||
};
|
||||
|
||||
root.getTxNote = function(wallet, txid, cb) {
|
||||
wallet.getTxNote({
|
||||
txid: txid
|
||||
|
|
@ -634,7 +726,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
};
|
||||
|
||||
root.getTx = function(wallet, txid, cb) {
|
||||
|
||||
function finish(list) {
|
||||
var tx = lodash.find(list, {
|
||||
txid: txid
|
||||
|
|
@ -651,7 +742,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
limitTx: txid
|
||||
}, function(err, txHistory) {
|
||||
if (err) return cb(err);
|
||||
|
||||
finish(txHistory);
|
||||
});
|
||||
}
|
||||
|
|
@ -675,16 +765,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
root.getTxHistory = function(wallet, opts, cb) {
|
||||
opts = opts || {};
|
||||
|
||||
var walletId = wallet.credentials.walletId;
|
||||
|
||||
if (!wallet.isComplete()) return cb();
|
||||
|
||||
function isHistoryCached() {
|
||||
return wallet.completeHistory && wallet.completeHistory.isValid;
|
||||
};
|
||||
|
||||
// disable caching
|
||||
//if (isHistoryCached() && !opts.force) return cb(null, wallet.completeHistory);
|
||||
// var historyIsCached = wallet.completeHistory && wallet.completeHistory.isValid;
|
||||
// if (historyIsCached && !opts.force) return cb(null, wallet.completeHistory);
|
||||
|
||||
$log.debug('Updating Transaction History');
|
||||
|
||||
|
|
|
|||
|
|
@ -366,4 +366,6 @@ a.item {
|
|||
|
||||
.loading-wallet svg {
|
||||
margin-top: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
<a ng-show="walletNotRegistered" ng-click="recreate()" translate>Tap to recreate</a>
|
||||
<a ng-show="updateStatusError" ng-click="updateAll(true)" translate>Tap to retry</a>
|
||||
</div>
|
||||
<span ng-click="onRefresh()" class="right" ng-show="(!updatingStatus && !updatingTxHistory)">↻</span>
|
||||
<ion-spinner class="spinner-dark recent right loading-wallet" icon="crescent" ng-show="(updatingStatus || updatingTxHistory) &&
|
||||
!walletNotRegistered && !updateStatusError && !updateTxHistoryError"></ion-spinner>
|
||||
<span ng-click="onRefresh()" class="right" ng-show="(!updatingStatus && !vm.updatingTxHistory && !vm.gettingInitialHistory)">↻</span>
|
||||
<ion-spinner class="spinner-dark recent right loading-wallet" icon="crescent" ng-show="(updatingStatus || vm.updatingTxHistory || vm.gettingInitialHistory) &&
|
||||
!walletNotRegistered && !updateStatusError && !vm.updateTxHistoryFailed"></ion-spinner>
|
||||
|
||||
<div>
|
||||
<span ng-show="wallet.status.wallet.singleAddress" class="size-12"><span translate>Auditable</span></span>
|
||||
|
|
|
|||
|
|
@ -161,18 +161,18 @@
|
|||
<!-- Transactions -->
|
||||
|
||||
<div class="wallet-details__no-transaction"
|
||||
ng-show="!txHistory[0] && !updatingTxHistory && !updateTxHistoryError && !updateStatusError" translate>
|
||||
ng-show="!txHistory[0] && !vm.gettingInitialHistory && !vm.updateTxHistoryFailed && !updateStatusError" translate>
|
||||
No transactions yet
|
||||
</div>
|
||||
|
||||
|
||||
<div class="wallet-details__no-update-history"
|
||||
ng-show="!txHistory[0] && !updatingTxHistory && updateTxHistoryError" translate>
|
||||
ng-show="!txHistory[0] && !vm.gettingInitialHistory && vm.updateTxHistoryFailed" translate>
|
||||
Could not update transaction history
|
||||
</div>
|
||||
|
||||
|
||||
<div ng-show="updatingTxHistory && updatingTxHistoryProgress>5" class="wallet-details__updating-history">
|
||||
<div ng-show="vm.gettingInitialHistory && updatingTxHistoryProgress>5" class="wallet-details__updating-history">
|
||||
<span translate>Updating transaction history. Please stand by.</span><br>
|
||||
<span translate>{{updatingTxHistoryProgress}} transactions downloaded</span>
|
||||
</div>
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<ion-infinite-scroll
|
||||
ng-if="txHistory[0] && !updatingTxHistory && txHistoryShowMore"
|
||||
ng-if="txHistory[0] && vm.allowInfiniteScroll"
|
||||
on-infinite="showMore()"
|
||||
distance="1%">
|
||||
</ion-infinite-scroll>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue