Merge pull request #346 from Bitcoin-com/wallet/task/593
Bug - 593 - Update confirmations on cached transactions
This commit is contained in:
commit
46413fa6aa
6 changed files with 65 additions and 33 deletions
10
Gruntfile.js
10
Gruntfile.js
|
|
@ -65,6 +65,9 @@ module.exports = function(grunt) {
|
||||||
run_android: {
|
run_android: {
|
||||||
command: 'cordova run android --device',
|
command: 'cordova run android --device',
|
||||||
},
|
},
|
||||||
|
run_android_emulator: {
|
||||||
|
command: 'cordova run android --emulator',
|
||||||
|
},
|
||||||
sign_android: {
|
sign_android: {
|
||||||
// When the build log outputs "Built the following apk(s):", it seems to need the filename to start with "android-release".
|
// When the build log outputs "Built the following apk(s):", it seems to need the filename to start with "android-release".
|
||||||
// It looks like it simply lists all apk files starting with "android-release"
|
// It looks like it simply lists all apk files starting with "android-release"
|
||||||
|
|
@ -363,13 +366,14 @@ module.exports = function(grunt) {
|
||||||
grunt.registerTask('build-mobile-release', ['build-ios-release', 'build-android-release']);
|
grunt.registerTask('build-mobile-release', ['build-ios-release', 'build-android-release']);
|
||||||
|
|
||||||
// Build ios
|
// Build ios
|
||||||
grunt.registerTask('start-ios', ['exec:build_ios_debug', 'exec:xcode']);
|
grunt.registerTask('start-ios', ['default', 'exec:build_ios_debug', 'exec:xcode']);
|
||||||
grunt.registerTask('build-ios-debug', ['exec:build_ios_debug']);
|
grunt.registerTask('build-ios-debug', ['default', 'exec:build_ios_debug']);
|
||||||
grunt.registerTask('build-ios-release', ['prod', 'exec:build_ios_release']);
|
grunt.registerTask('build-ios-release', ['prod', 'exec:build_ios_release']);
|
||||||
|
|
||||||
// Build android
|
// Build android
|
||||||
grunt.registerTask('start-android', ['build-android-debug', 'exec:run_android']);
|
grunt.registerTask('start-android', ['build-android-debug', 'exec:run_android']);
|
||||||
grunt.registerTask('build-android-debug', ['exec:build_android_debug']);
|
grunt.registerTask('build-android-debug', ['default', 'exec:build_android_debug']);
|
||||||
|
grunt.registerTask('start-android-emulator', ['build-android-debug', 'exec:run_android_emulator']);
|
||||||
grunt.registerTask('build-android-release', ['prod', 'exec:build_android_release', 'sign-android']);
|
grunt.registerTask('build-android-release', ['prod', 'exec:build_android_release', 'sign-android']);
|
||||||
grunt.registerTask('sign-android', ['exec:sign_android']);
|
grunt.registerTask('sign-android', ['exec:sign_android']);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@
|
||||||
"start": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0",
|
"start": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0",
|
||||||
"start:chrome": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0 --browser \"google chrome\"",
|
"start:chrome": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0 --browser \"google chrome\"",
|
||||||
"start:android": "grunt start-android",
|
"start:android": "grunt start-android",
|
||||||
|
"start:android-emulator": "grunt start-android",
|
||||||
"start:android-log": "grunt start-android && npm run log:android",
|
"start:android-log": "grunt start-android && npm run log:android",
|
||||||
"start:ios": "grunt start-ios",
|
"start:ios": "grunt start-ios",
|
||||||
"start:windows": "npm run build:www && npm run build:windows",
|
"start:windows": "npm run build:www && npm run build:windows",
|
||||||
|
|
|
||||||
|
|
@ -400,8 +400,8 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
|
|
||||||
var refreshInterval;
|
var refreshInterval;
|
||||||
|
|
||||||
$scope.$on("$ionicView.afterEnter", function(event, data) {
|
$scope.$on("$ionicView.afterEnter", function onAfterEnter(event, data) {
|
||||||
$scope.updateAll();
|
$scope.updateAll(true, true);
|
||||||
// refreshAmountSection();
|
// refreshAmountSection();
|
||||||
refreshInterval = $interval($scope.onRefresh, 10 * 1000);
|
refreshInterval = $interval($scope.onRefresh, 10 * 1000);
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,9 @@ angular.module('copayApp.services').factory('bitcoincomService', function(gettex
|
||||||
};
|
};
|
||||||
|
|
||||||
var register = function() {
|
var register = function() {
|
||||||
|
if (!platformInfo.isAndroid) { // To comply with Google Play policies
|
||||||
nextStepsService.register(cashGamesItem);
|
nextStepsService.register(cashGamesItem);
|
||||||
|
}
|
||||||
nextStepsService.register(newsItem);
|
nextStepsService.register(newsItem);
|
||||||
nextStepsService.register(poolItem);
|
nextStepsService.register(poolItem);
|
||||||
nextStepsService.register(toolsItem);
|
nextStepsService.register(toolsItem);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ angular.module('copayApp.services')
|
||||||
isoCode: 'en',
|
isoCode: 'en',
|
||||||
rateCode: 'USD'
|
rateCode: 'USD'
|
||||||
}, {
|
}, {
|
||||||
name: 'català',
|
name: 'Català',
|
||||||
isoCode: 'ca',
|
isoCode: 'ca',
|
||||||
rateCode: 'EUR'
|
rateCode: 'EUR'
|
||||||
},{
|
},{
|
||||||
|
|
@ -59,10 +59,6 @@ angular.module('copayApp.services')
|
||||||
name: 'Português',
|
name: 'Português',
|
||||||
isoCode: 'pt',
|
isoCode: 'pt',
|
||||||
rateCode: 'EUR'
|
rateCode: 'EUR'
|
||||||
}, {
|
|
||||||
name: 'русский язык',
|
|
||||||
isoCode: 'ru',
|
|
||||||
rateCode: 'RUB'
|
|
||||||
}, {
|
}, {
|
||||||
name: '한국어',
|
name: '한국어',
|
||||||
isoCode: 'ko',
|
isoCode: 'ko',
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@
|
||||||
// How much to overlap on each end of the page, for mitigating inconsistent sort order.
|
// How much to overlap on each end of the page, for mitigating inconsistent sort order.
|
||||||
var PAGE_OVERLAP_FRACTION = 0.2;
|
var PAGE_OVERLAP_FRACTION = 0.2;
|
||||||
var PAGE_OVERLAP = Math.floor(PAGE_SIZE * PAGE_OVERLAP_FRACTION);
|
var PAGE_OVERLAP = Math.floor(PAGE_SIZE * PAGE_OVERLAP_FRACTION);
|
||||||
// The amount of transactions in the new overlapping resultset that we already know about.
|
// The fraction 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.
|
// 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 MIN_KNOWN_TX_OVERLAP_FRACTION = 0.5;
|
||||||
|
|
||||||
var SAFE_CONFIRMATIONS = 6;
|
var SAFE_CONFIRMATIONS = 6;
|
||||||
|
|
||||||
|
|
@ -27,26 +27,34 @@
|
||||||
|
|
||||||
function addEarlyTransactions(walletId, cachedTxs, newTxs) {
|
function addEarlyTransactions(walletId, cachedTxs, newTxs) {
|
||||||
|
|
||||||
var cachedTxIds = {};
|
var cachedTxIndexFromId = {};
|
||||||
cachedTxs.forEach(function forCachedTx(tx){
|
cachedTxs.forEach(function forCachedTx(tx){
|
||||||
cachedTxIds[tx.txid] = true;
|
cachedTxIndexFromId[tx.txid] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var confirmationsUpdated = false;
|
||||||
var someTransactionsWereNew = false;
|
var someTransactionsWereNew = false;
|
||||||
var overlappingTxsCount = 0;
|
var overlappingTxsCount = 0;
|
||||||
|
|
||||||
newTxs.forEach(function forNewTx(tx){
|
newTxs.forEach(function forNewTx(tx){
|
||||||
if (cachedTxIds[tx.txid]) {
|
if (typeof cachedTxIndexFromId[tx.txid] === "undefined") {
|
||||||
overlappingTxsCount++;
|
|
||||||
} else {
|
|
||||||
someTransactionsWereNew = true;
|
someTransactionsWereNew = true;
|
||||||
cachedTxs.push(tx);
|
cachedTxs.push(tx);
|
||||||
|
} else {
|
||||||
|
var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx);
|
||||||
|
confirmationsUpdated = confirmationsUpdated || txUpdated;
|
||||||
|
overlappingTxsCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (overlappingTxsCount >= MIN_KNOWN_TX_OVERLAP) { // We are good
|
var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP);
|
||||||
|
console.log('overlappingTxFraction:', overlappingTxFraction);
|
||||||
|
|
||||||
|
if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good
|
||||||
if (someTransactionsWereNew) {
|
if (someTransactionsWereNew) {
|
||||||
saveTxHistory(walletId, cachedTxs);
|
saveTxHistory(walletId, cachedTxs);
|
||||||
|
} else if (confirmationsUpdated) {
|
||||||
|
saveTxHistory(walletId, cachedTxs);
|
||||||
} else if (overlappingTxsCount === newTxs.length) {
|
} else if (overlappingTxsCount === newTxs.length) {
|
||||||
allTransactionsFetched = true;
|
allTransactionsFetched = true;
|
||||||
}
|
}
|
||||||
|
|
@ -62,30 +70,38 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLatestTransactions(walletId, cachedTxs, newTxs) {
|
function addLatestTransactions(walletId, cachedTxs, newTxs) {
|
||||||
var cachedTxIds = {};
|
var cachedTxIndexFromId = {};
|
||||||
cachedTxs.forEach(function forCachedTx(tx){
|
cachedTxs.forEach(function forCachedTx(tx, txIndex){
|
||||||
cachedTxIds[tx.txid] = true;
|
cachedTxIndexFromId[tx.txid] = txIndex;
|
||||||
});
|
});
|
||||||
|
|
||||||
var someTransactionsWereNew = false;
|
var someTransactionsWereNew = false;
|
||||||
|
var confirmationsUpdated = false;
|
||||||
var overlappingTxsCount = 0;
|
var overlappingTxsCount = 0;
|
||||||
var uniqueNewTxs = [];
|
var uniqueNewTxs = [];
|
||||||
|
|
||||||
newTxs.forEach(function forNewTx(tx){
|
newTxs.forEach(function forNewTx(tx){
|
||||||
if (cachedTxIds[tx.txid]) {
|
if (typeof cachedTxIndexFromId[tx.txid] === "undefined") {
|
||||||
overlappingTxsCount++;
|
|
||||||
} else {
|
|
||||||
someTransactionsWereNew = true;
|
someTransactionsWereNew = true;
|
||||||
uniqueNewTxs.push(tx);
|
uniqueNewTxs.push(tx);
|
||||||
|
} else {
|
||||||
|
var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx);
|
||||||
|
confirmationsUpdated = confirmationsUpdated || txUpdated;
|
||||||
|
overlappingTxsCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (overlappingTxsCount >= MIN_KNOWN_TX_OVERLAP) { // We are good
|
var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP);
|
||||||
|
|
||||||
|
if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good
|
||||||
if (someTransactionsWereNew) {
|
if (someTransactionsWereNew) {
|
||||||
var allTxs = uniqueNewTxs.concat(cachedTxs);
|
var allTxs = uniqueNewTxs.concat(cachedTxs);
|
||||||
saveTxHistory(walletId, allTxs);
|
saveTxHistory(walletId, allTxs);
|
||||||
return allTxs;
|
return allTxs;
|
||||||
} else {
|
} else {
|
||||||
|
if (confirmationsUpdated) {
|
||||||
|
saveTxHistory(walletId, cachedTxs);
|
||||||
|
}
|
||||||
return cachedTxs;
|
return cachedTxs;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -99,6 +115,8 @@
|
||||||
|
|
||||||
// Only clear the cache once we have received new transactions from the server.
|
// Only clear the cache once we have received new transactions from the server.
|
||||||
/**
|
/**
|
||||||
|
* @param wallet
|
||||||
|
* @param start
|
||||||
* @param {function(err, txs)} cb - transactions is always an array, may be empty
|
* @param {function(err, txs)} cb - transactions is always an array, may be empty
|
||||||
*/
|
*/
|
||||||
function fetchTxHistoryByPage(wallet, start, cb) {
|
function fetchTxHistoryByPage(wallet, start, cb) {
|
||||||
|
|
@ -182,7 +200,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
return processedTxs;
|
return processedTxs;
|
||||||
};
|
}
|
||||||
|
|
||||||
function saveTxHistory(walletId, processedTxs) {
|
function saveTxHistory(walletId, processedTxs) {
|
||||||
storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){
|
storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){
|
||||||
|
|
@ -192,9 +210,25 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the cached tx was updated
|
||||||
|
* @param {*} cachedTxs
|
||||||
|
* @param {*} cachedTxIndexFromId - Indices for cachedTxs, based on txid
|
||||||
|
* @param {*} tx - The most recent tx info
|
||||||
|
*/
|
||||||
|
function updateCachedTx(cachedTxs, cachedTxIndexFromId, tx) {
|
||||||
|
var updated = false;
|
||||||
|
var txIndex = cachedTxIndexFromId[tx.txid];
|
||||||
|
var cachedTx = cachedTxs[txIndex];
|
||||||
|
|
||||||
|
if (cachedTx.confirmations < SAFE_CONFIRMATIONS && tx.confirmations > cachedTx.confirmations) {
|
||||||
|
cachedTxs[txIndex].confirmations = tx.confirmations;
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) {
|
function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) {
|
||||||
|
|
||||||
if (flushCacheOnNew) {
|
if (flushCacheOnNew) {
|
||||||
fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){
|
fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -235,10 +269,5 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
Loading…
Add table
Add a link
Reference in a new issue