Merged sprint 21.

This commit is contained in:
Brendon Duncan 2018-09-21 17:16:18 -07:00
commit 4d623d51d7
11 changed files with 1121 additions and 1039 deletions

View file

@ -366,13 +366,13 @@ module.exports = function(grunt) {
grunt.registerTask('build-mobile-release', ['build-ios-release', 'build-android-release']);
// Build ios
grunt.registerTask('start-ios', ['exec:build_ios_debug', 'exec:xcode']);
grunt.registerTask('build-ios-debug', ['exec:build_ios_debug']);
grunt.registerTask('start-ios', ['default', 'exec:build_ios_debug', 'exec:xcode']);
grunt.registerTask('build-ios-debug', ['default', 'exec:build_ios_debug']);
grunt.registerTask('build-ios-release', ['prod', 'exec:build_ios_release']);
// Build 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('sign-android', ['exec:sign_android']);

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ angular.module('copayApp.controllers').controller('shapeshiftController', functi
walletsBtc = profileService.getWallets({coin: 'btc'});
walletsBch = profileService.getWallets({coin: 'bch'});
$scope.fromWallets = lodash.filter(walletsBtc.concat(walletsBch), function(w) {
return w.status.balance.availableAmount > 0;
return (w.status && w.status.balance && w.status.balance.availableAmount > 0);
});
$scope.singleFromWallet = $scope.fromWallets.length === 1;

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, sendFlowService, txFormatService, soundService, clipboardService) {
var CLOSE_NORMAL = 1000;
var listeners = [];
$scope.bchAddressType = { type: 'cashaddr' };
var bchAddresses = {};
@ -10,12 +11,11 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
$scope.isCordova = platformInfo.isCordova;
$scope.isNW = platformInfo.isNW;
var currentAddressSocket = {};
var paymentSubscriptionObj = { op:"addr_sub" }
var config;
var currentAddressSocket = null;
var paymentSubscriptionObj = { op:'addr_sub' };
$scope.displayBalanceAsFiat = true;
$scope.$on('$ionicView.beforeLeave', onBeforeLeave);
$scope.requestSpecificAmount = function() {
sendFlowService.start({
@ -24,6 +24,50 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
});
};
function connectSocket() {
// Close existing socket if not connected with current address
if (currentAddressSocket) {
currentAddressSocket.close([CLOSE_NORMAL]);
}
if ($scope.wallet.coin === 'bch') {
// listen to bch address
currentAddressSocket = new WebSocket('wss://ws.blockchain.info/bch/inv');
paymentSubscriptionObj.addr = $scope.addrBchLegacy;
} else {
// listen to btc address
currentAddressSocket = new WebSocket('wss://ws.blockchain.info/inv');
paymentSubscriptionObj.addr = $scope.addr;
}
// create subscription to address
var msg = JSON.stringify(paymentSubscriptionObj);
currentAddressSocket.onopen = function (event) {
currentAddressSocket.send(msg);
};
// listen for response
currentAddressSocket.onmessage = function (event) {
//console.log("message received:" + event.data);
receivedPayment(event.data);
};
currentAddressSocket.onclose = function(event) {
if (event.code !== CLOSE_NORMAL) {
$log.debug('Socket was closed abnormally. Reconnect will be attempted in 1 second.');
$timeout(function() {
connectSocket();
}, 1000);
}
};
currentAddressSocket.onerror = function(err) {
console.error('Socket encountered error: ', err, 'Closing socket');
currentAddressSocket.close();
};
}
$scope.setAddress = function(newAddr, copyAddress) {
$scope.addr = null;
if (!$scope.wallet || $scope.generatingAddress || !$scope.wallet.isComplete()) return;
@ -36,49 +80,24 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
popupService.showAlert(err);
}
//close existing socket
if (currentAddressSocket.close === 'function') {
currentAddressSocket.close();
}
if ($scope.wallet.coin == 'bch') {
bchAddresses = bitcoinCashJsService.translateAddresses(addr);
$scope.addr = bchAddresses[$scope.bchAddressType.type];
$scope.addrBchLegacy = bchAddresses['legacy'];
// listen to bch address
currentAddressSocket = new WebSocket("wss://ws.blockchain.info/bch/inv");
paymentSubscriptionObj.addr = bchAddresses['legacy'];
if ($scope.wallet.coin === 'bch') {
bchAddresses = bitcoinCashJsService.translateAddresses(addr);
$scope.addr = bchAddresses[$scope.bchAddressType.type];
$scope.addrBchLegacy = bchAddresses['legacy'];
} else {
$scope.addr = addr;
// listen to btc address
currentAddressSocket = new WebSocket("wss://ws.blockchain.info/inv");
paymentSubscriptionObj.addr = $scope.addr
$scope.addr = addr;
}
connectSocket();
if (copyAddress === true) {
try {
clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr);
} catch (error) {
$log.debug("Error copying to clipboard:");
$log.debug('Error copying to clipboard:');
$log.debug(error);
}
}
// create subscription
var msg = JSON.stringify(paymentSubscriptionObj);
currentAddressSocket.onopen = function (event) {
//console.log("message sent: " + msg);
currentAddressSocket.send(msg);
}
// listen for response
currentAddressSocket.onmessage = function (event) {
//console.log("message received:" + event.data);
receivedPayment(event.data);
}
$timeout(function() {
$scope.$apply();
@ -164,7 +183,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
// Notify new tx
$scope.$emit('bwsEvent', $scope.wallet.id);
$scope.$apply(function () {
$scope.showingPaymentReceived = true;
});
@ -233,6 +251,10 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
}
};
function onBeforeLeave() {
currentAddressSocket.close([CLOSE_NORMAL]);
}
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.wallets = profileService.getWallets();
$scope.singleWallet = $scope.wallets.length == 1;
@ -258,7 +280,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
configService.whenAvailable(function(_config) {
$scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat';
config = _config;
});
});

View file

@ -203,6 +203,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
function updateTxHistoryFromCachedData() {
$scope.vm.gettingCachedHistory = true;
walletHistoryService.getCachedTxHistory($scope.wallet.id, function onGetCachedTxHistory(err, txHistory){
$scope.vm.gettingCachedHistory = false;
if (err) {
@ -400,8 +401,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
var refreshInterval;
$scope.$on("$ionicView.afterEnter", function(event, data) {
$scope.updateAll();
$scope.$on("$ionicView.afterEnter", function onAfterEnter(event, data) {
updateTxHistoryFromCachedData();
$scope.updateAll(true, true);
// refreshAmountSection();
refreshInterval = $interval($scope.onRefresh, 10 * 1000);
$timeout(function() {

View file

@ -1,189 +1,204 @@
'use strict';
angular.module('copayApp.controllers').controller('walletSelectorController', function($scope, $state, sendFlowService, configService, gettextCatalog, profileService, txFormatService) {
(function () {
var fromWalletId = '';
var priceDisplayAsFiat = false;
var unitDecimals = 0;
var unitsFromSatoshis = 0;
angular
.module('copayApp.controllers')
.controller('walletSelectorController', walletSelectorController);
$scope.$on("$ionicView.beforeEnter", onBeforeEnter);
$scope.$on("$ionicView.enter", onEnter);
function walletSelectorController ($scope, $state, sendFlowService, configService, gettextCatalog, ongoingProcess, profileService, walletService, txFormatService) {
var fromWalletId = '';
var priceDisplayAsFiat = false;
var unitDecimals = 0;
var unitsFromSatoshis = 0;
function onBeforeEnter(event, data) {
if (data.direction == "back") {
sendFlowService.state.pop();
}
$scope.$on("$ionicView.beforeEnter", onBeforeEnter);
$scope.$on("$ionicView.enter", onEnter);
$scope.params = sendFlowService.state.getClone();
function onBeforeEnter(event, data) {
if (data.direction == "back") {
sendFlowService.state.pop();
}
console.log('walletSelector onBeforeEnter after back sendflow', $scope.params);
$scope.params = sendFlowService.state.getClone();
var config = configService.getSync().wallet.settings;
priceDisplayAsFiat = config.priceDisplay === 'fiat';
unitDecimals = config.unitDecimals;
unitsFromSatoshis = 1 / config.unitToSatoshi;
console.log('walletSelector onBeforeEnter after back sendflow', $scope.params);
if ($scope.params.isWalletTransfer) {
$scope.sendFlowTitle = gettextCatalog.getString('Transfer between wallets');
} else if (!$scope.params.thirdParty) {
$scope.sendFlowTitle = gettextCatalog.getString('Send');
}
var config = configService.getSync().wallet.settings;
priceDisplayAsFiat = config.priceDisplay === 'fiat';
unitDecimals = config.unitDecimals;
unitsFromSatoshis = 1 / config.unitToSatoshi;
$scope.coin = false; // Wallets to show (for destination screen or contacts)
$scope.type = $scope.params['fromWalletId'] ? 'destination' : 'origin'; // origin || destination
fromWalletId = $scope.params['fromWalletId'];
if ($scope.params.isWalletTransfer) {
$scope.sendFlowTitle = gettextCatalog.getString('Transfer between wallets');
} else if (!$scope.params.thirdParty) {
$scope.sendFlowTitle = gettextCatalog.getString('Send');
}
if ($scope.type === 'destination' && $scope.params.toAddress) {
$state.transitionTo(getNextStep($scope.params));
}
$scope.coin = false; // Wallets to show (for destination screen or contacts)
$scope.type = $scope.params['fromWalletId'] ? 'destination' : 'origin'; // origin || destination
fromWalletId = $scope.params['fromWalletId'];
if ($scope.params.coin) {
$scope.coin = $scope.params.coin; // Contacts have a coin embedded
}
if ($scope.type === 'destination' && $scope.params.toAddress) {
$state.transitionTo(getNextStep($scope.params));
}
if ($scope.params.amount) { // There is an amount, so presume that it is a payment request
$scope.sendFlowTitle = gettextCatalog.getString('Payment Request');
$scope.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isPaymentRequest = true;
}
if ($scope.params.thirdParty) {
$scope.thirdParty = $scope.params.thirdParty;
}
};
if ($scope.params.coin) {
$scope.coin = $scope.params.coin; // Contacts have a coin embedded
}
function onEnter (event, data) {
configService.whenAvailable(function(config) {
$scope.selectedPriceDisplay = config.wallet.settings.priceDisplay;
});
if ($scope.params.amount) { // There is an amount, so presume that it is a payment request
$scope.sendFlowTitle = gettextCatalog.getString('Payment Request');
$scope.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isPaymentRequest = true;
}
if ($scope.params.thirdParty) {
$scope.thirdParty = $scope.params.thirdParty;
}
};
if ($scope.thirdParty) {
// Third party services specific logic
handleThirdPartyIfShapeshift();
}
prepareWalletLists();
formatRequestedAmount();
};
function formatRequestedAmount() {
if ($scope.params.amount) {
var cryptoAmount = (unitsFromSatoshis * $scope.params.amount).toFixed(unitDecimals);
var cryptoCoin = $scope.coin.toUpperCase();
txFormatService.formatAlternativeStr($scope.coin, $scope.params.amount, function onFormatAlternativeStr(formatted){
if (formatted) {
var fiatParts = formatted.split(' ');
var fiatAmount = fiatParts[0];
var fiatCurrrency = fiatParts.length > 1 ? fiatParts[1] : '';
if (priceDisplayAsFiat) {
$scope.requestAmount = fiatAmount;
$scope.requestCurrency = fiatCurrrency;
$scope.requestAmountSecondary = cryptoAmount;
$scope.requestCurrencySecondary = cryptoCoin;
} else {
$scope.requestAmount = cryptoAmount;
$scope.requestCurrency = cryptoCoin;
$scope.requestAmountSecondary = fiatAmount;
$scope.requestCurrencySecondary = fiatCurrrency;
}
$scope.$apply();
}
function onEnter (event, data) {
configService.whenAvailable(function(config) {
$scope.selectedPriceDisplay = config.wallet.settings.priceDisplay;
});
}
}
function handleThirdPartyIfShapeshift() {
console.log($scope.thirdParty, $scope.coin);
if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
$scope.coin = profileService.getWallet(fromWalletId).coin;
if ($scope.coin === 'bch') {
$scope.coin = 'btc';
} else {
$scope.coin = 'bch';
if ($scope.thirdParty) {
// Third party services specific logic
handleThirdPartyIfShapeshift();
}
}
}
function prepareWalletLists() {
var walletsAll = [];
var walletsSufficientFunds = [];
$scope.walletsInsufficientFunds = []; // For origin screen
if ($scope.type === 'origin') {
$scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from');
prepareWalletLists();
formatRequestedAmount();
};
function formatRequestedAmount() {
if ($scope.params.amount) {
var cryptoAmount = (unitsFromSatoshis * $scope.params.amount).toFixed(unitDecimals);
var cryptoCoin = $scope.coin.toUpperCase();
walletsAll = profileService.getWallets({coin: $scope.coin});
txFormatService.formatAlternativeStr($scope.coin, $scope.params.amount, function onFormatAlternativeStr(formatted){
if (formatted) {
var fiatParts = formatted.split(' ');
var fiatAmount = fiatParts[0];
var fiatCurrrency = fiatParts.length > 1 ? fiatParts[1] : '';
walletsAll.forEach(function forWallet(wallet){
if (wallet.status.availableBalanceSat > $scope.params.amount) {
walletsSufficientFunds.push(wallet);
} else {
$scope.walletsInsufficientFunds.push(wallet);
if (priceDisplayAsFiat) {
$scope.requestAmount = fiatAmount;
$scope.requestCurrency = fiatCurrrency;
$scope.requestAmountSecondary = cryptoAmount;
$scope.requestCurrencySecondary = cryptoCoin;
} else {
$scope.requestAmount = cryptoAmount;
$scope.requestCurrency = cryptoCoin;
$scope.requestAmountSecondary = fiatAmount;
$scope.requestCurrencySecondary = fiatCurrrency;
}
$scope.$apply();
}
});
}
}
if ($scope.coin === 'btc') {
$scope.walletsBtc = walletsSufficientFunds;
function handleThirdPartyIfShapeshift() {
console.log($scope.thirdParty, $scope.coin);
if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
$scope.coin = profileService.getWallet(fromWalletId).coin;
if ($scope.coin === 'bch') {
$scope.coin = 'btc';
} else {
$scope.walletsBch = walletsSufficientFunds;
$scope.coin = 'bch';
}
}
}
} else if ($scope.coin) {
walletsAll = profileService.getWallets({coin: $scope.coin});
walletsAll.forEach(function forWallet(wallet){
if (wallet.status.availableBalanceSat > 0) {
walletsSufficientFunds.push(wallet);
function prepareWalletLists() {
var walletsAll = [];
var walletsSufficientFunds = [];
$scope.walletsInsufficientFunds = []; // For origin screen
if ($scope.type === 'origin') {
$scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from');
if ($scope.params.amount || $scope.coin) {
walletsAll = profileService.getWallets({coin: $scope.coin});
ongoingProcess.set('scanning', true);
walletsAll.forEach(function forWallet(wallet) {
if (!wallet.status && !wallet.cachedStatus) {
walletService.getStatus(wallet, {}, function(err, status) {
wallet.status = status;
if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) {
walletsSufficientFunds.push(wallet);
} else {
$scope.walletsInsufficientFunds.push(wallet);
}
if ($scope.coin === 'btc') { // As this is a promise
$scope.walletsBtc = walletsSufficientFunds;
} else {
$scope.walletsBch = walletsSufficientFunds;
}
ongoingProcess.set('scanning', false);
});
} else {
var walletStatus = null;
if (wallet.status && wallet.status.isValid) {
walletStatus = wallet.status;
} else if (wallet.cachedStatus && wallet.status.isValid) {
walletStatus = wallet.cachedStatus;
}
if (walletStatus && walletStatus.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) {
walletsSufficientFunds.push(wallet);
} else {
$scope.walletsInsufficientFunds.push(wallet);
}
ongoingProcess.set('scanning', false);
}
});
if ($scope.coin === 'btc') {
$scope.walletsBtc = walletsSufficientFunds;
} else {
$scope.walletsInsufficientFunds.push(wallet);
$scope.walletsBch = walletsSufficientFunds;
}
});
if ($scope.coin === 'btc') {
$scope.walletsBtc = walletsSufficientFunds;
} else {
$scope.walletsBch = walletsSufficientFunds;
$scope.walletsBch = profileService.getWallets({coin: 'bch', hasFunds: true});
$scope.walletsBtc = profileService.getWallets({coin: 'btc', hasFunds: true});
$scope.walletsInsufficientFunds = profileService.getWallets({coin: $scope.coin, hasNoFunds: true});
}
} else {
$scope.walletsBch = profileService.getWallets({coin: 'bch', hasFunds: true});
$scope.walletsBtc = profileService.getWallets({coin: 'btc', hasFunds: true});
$scope.walletsInsufficientFunds = profileService.getWallets({coin: $scope.coin, hasNoFunds: true});
}
} else if ($scope.type === 'destination') {
if (!$scope.coin) { // Allow for the coin to be set by a third party
$scope.fromWallet = profileService.getWallet(fromWalletId);
$scope.coin = $scope.fromWallet.coin; // Only show wallets with the select origin wallet coin
}
$scope.headerTitle = gettextCatalog.getString('Choose a wallet to send to');
} else if ($scope.type === 'destination') {
if (!$scope.coin) { // Allow for the coin to be set by a third party
$scope.fromWallet = profileService.getWallet(fromWalletId);
$scope.coin = $scope.fromWallet.coin; // Only show wallets with the select origin wallet coin
}
$scope.headerTitle = gettextCatalog.getString('Choose a wallet to send to');
if ($scope.coin === 'btc') { // if no specific coin is set or coin is set btc
$scope.walletsBtc = profileService.getWallets({coin: $scope.coin});
} else {
$scope.walletsBch = profileService.getWallets({coin: $scope.coin});
if ($scope.coin === 'btc') { // if no specific coin is set or coin is set btc
$scope.walletsBtc = profileService.getWallets({coin: $scope.coin});
} else {
$scope.walletsBch = profileService.getWallets({coin: $scope.coin});
}
}
}
}
$scope.useWallet = function(wallet) {
var params = sendFlowService.state.getClone();
if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from
params.fromWalletId = wallet.id;
} else { // we're on the destination screen, set wallet to send to
params.toWalletId = wallet.id;
$scope.useWallet = function(wallet) {
var params = sendFlowService.state.getClone();
if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from
params.fromWalletId = wallet.id;
} else { // we're on the destination screen, set wallet to send to
params.toWalletId = wallet.id;
}
sendFlowService.goNext(params);
};
$scope.goBack = function() {
sendFlowService.router.goBack();
}
sendFlowService.goNext(params);
};
$scope.goBack = function() {
sendFlowService.router.goBack();
}
});
})();

View file

@ -12,6 +12,7 @@
totalBalanceSat: '@',
// The Wallet object is sometimes not stringify()-able, so not interpolatable,
// so can't be passed to a directive.
walletCoin: '@',
walletStatus: '@',
walletCachedBalance: '@',
walletCachedBalanceUpdatedOn: '@',
@ -31,7 +32,6 @@
});
function displayCryptoBalance(walletStatus, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatus) {
console.log('displayCryptoBalance()');
if (walletStatus && walletStatus.isValid && walletStatus.totalBalanceStr) {
setDisplay(walletStatus.totalBalanceStr, '');
@ -52,7 +52,7 @@
setDisplay('', '');
}
function displayFiatBalance(walletStatus, walletCachedStatus) {
function displayFiatBalance(walletStatus, walletCachedStatus, walletCoin) {
var displayAmount = '';
if (walletStatus && walletStatus.isValid && walletStatus.alternativeBalanceAvailable) {
displayAmount = walletStatus.totalBalanceAlternative + ' ' + walletStatus.alternativeIsoCode;
@ -66,7 +66,7 @@
return;
}
getFiatBalance(wallet);
getFiatBalance(walletStatus, walletCachedStatus, walletCoin);
}
function formatBalance() {
@ -94,19 +94,30 @@
}
if (displayAsFiat) {
displayFiatBalance(walletStatusObj, walletCachedStatusObj);
displayFiatBalance(walletStatusObj, walletCachedStatusObj, $scope.walletCoin);
}
}
function getFiatBalance(wallet) {
if (!(wallet.status && wallet.status.isValid)) {
$log.warn('Abandoning call to get fiat balance, because no valid wallet status.');
function getFiatBalance(walletStatus, walletCachedStatus, walletCoin) {
var totalBalanceSat = null;
if (walletStatus && walletStatus.isValid) {
totalBalanceSat = walletStatus.totalBalanceSat
} else if (walletCachedStatus && walletCachedStatus.isValid) {
totalBalanceSat = walletCachedStatus.totalBalanceSat
}
// 0 is valid
if (totalBalanceSat === null) {
$log.warn('Abandoning call to get fiat balance, because no valid wallet status (cached or otherwise).');
return;
}
txFormatService.formatAlternativeStr(wallet.coin, wallet.status.totalBalanceSat, function onFormatAlernativeStr(formatted) {
txFormatService.formatAlternativeStr(walletCoin, totalBalanceSat, function onFormatAlernativeStr(formatted) {
if (formatted) {
setDisplay(formatted, '');
} else {
$log.error('Failed to format fiat balance of wallet.');
}
});
}

View file

@ -75,9 +75,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
var showName = $filter('translate')(processNames[name] || name);
if (customHandler) {
customHandler(processName, showName, isOn);
} else if (root.onGoingProcessName) {
if (root.onGoingProcessName) {
var tmpl;
if (isWindowsPhoneApp) tmpl = '<div>' + showName + '</div>';
else tmpl = '<div class="item-icon-left">' + showName + '<ion-spinner class="spinner-stable" icon="lines"></ion-spinner></div>';
@ -87,6 +85,10 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
} else {
$ionicLoading.hide();
}
if (customHandler) {
customHandler(processName, showName, isOn);
}
};
return root;

View file

@ -27,20 +27,23 @@
function addEarlyTransactions(walletId, cachedTxs, newTxs) {
var cachedTxIds = {};
var cachedTxIndexFromId = {};
cachedTxs.forEach(function forCachedTx(tx){
cachedTxIds[tx.txid] = true;
cachedTxIndexFromId[tx.txid] = true;
});
var confirmationsUpdated = false;
var someTransactionsWereNew = false;
var overlappingTxsCount = 0;
newTxs.forEach(function forNewTx(tx){
if (cachedTxIds[tx.txid]) {
overlappingTxsCount++;
} else {
if (typeof cachedTxIndexFromId[tx.txid] === "undefined") {
someTransactionsWereNew = true;
cachedTxs.push(tx);
} else {
var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx);
confirmationsUpdated = confirmationsUpdated || txUpdated;
overlappingTxsCount++;
}
});
@ -50,6 +53,8 @@
if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good
if (someTransactionsWereNew) {
saveTxHistory(walletId, cachedTxs);
} else if (confirmationsUpdated) {
saveTxHistory(walletId, cachedTxs);
} else if (overlappingTxsCount === newTxs.length) {
allTransactionsFetched = true;
}
@ -65,21 +70,24 @@
}
function addLatestTransactions(walletId, cachedTxs, newTxs) {
var cachedTxIds = {};
cachedTxs.forEach(function forCachedTx(tx){
cachedTxIds[tx.txid] = true;
var cachedTxIndexFromId = {};
cachedTxs.forEach(function forCachedTx(tx, txIndex){
cachedTxIndexFromId[tx.txid] = txIndex;
});
var someTransactionsWereNew = false;
var confirmationsUpdated = false;
var overlappingTxsCount = 0;
var uniqueNewTxs = [];
newTxs.forEach(function forNewTx(tx){
if (cachedTxIds[tx.txid]) {
overlappingTxsCount++;
} else {
if (typeof cachedTxIndexFromId[tx.txid] === "undefined") {
someTransactionsWereNew = true;
uniqueNewTxs.push(tx);
} else {
var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx);
confirmationsUpdated = confirmationsUpdated || txUpdated;
overlappingTxsCount++;
}
});
@ -91,6 +99,9 @@
saveTxHistory(walletId, allTxs);
return allTxs;
} else {
if (confirmationsUpdated) {
saveTxHistory(walletId, cachedTxs);
}
return cachedTxs;
}
} else {
@ -104,6 +115,8 @@
// 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
*/
function fetchTxHistoryByPage(wallet, start, cb) {
@ -134,6 +147,7 @@
* @param {function(error, txs)} cb - txs is always an array, may be empty
*/
function getCachedTxHistory(walletId, cb) {
console.log('txhistory updateLocalTxHistoryByPage()');
storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){
if (err) {
return cb(err, []);
@ -187,7 +201,7 @@
});
return processedTxs;
};
}
function saveTxHistory(walletId, processedTxs) {
storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){
@ -197,9 +211,26 @@
});
}
/**
* 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) {
console.log('txhistory updaetLocalTxHistoryByPage()');
if (flushCacheOnNew) {
fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){
if (err) {
@ -240,10 +271,5 @@
});
}
}
}
})();

View file

@ -18,13 +18,12 @@
<h2>{{fromWallet.name}}</h2>
<wallet-balance
display-as-fiat="{{displayBalanceAsFiat}}"
wallet-coin="{{fromWallet.coin}}"
wallet-status="{{fromWallet.status}}"
wallet-cached-balance="{{fromWallet.cachedBalance}}"
wallet-cached-balance-updated-on="{{fromWallet.cachedBalanceUpdatedOn}}"
wallet-cached-status="{{fromWallet.cachedStatus}}"
total-balance-sat="{{fromWallet.status.totalBalanceSat}}"></wallet-balance>
<!--<p ng-show="vm.origin.balanceAmount">{{vm.origin.balanceAmount}} {{vm.origin.balanceCurrency}}</p>-->
<!--<formatted-amount value="{{fromWallet.status.totalBalanceStr ? fromWallet.status.totalBalanceStr : ( fromWallet.cachedBalance ? fromWallet.cachedBalance + (fromWallet.cachedBalanceUpdatedOn ? ' &middot; ' + ( fromWallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }}"></formatted-amount>-->
</div>
</div>
</div>

View file

@ -13,7 +13,7 @@
<div class="header--request__amount-alt" ng-show="requestAmountSecondary" translate>{{requestAmountSecondary}} {{requestCurrencySecondary}}</div>
</div>
<div class="wallets-header">
<div class="title">
<div class="title" ng-if="walletsBch.length > 0 || walletsBtc.length > 0 || walletsInsufficientFunds.length > 0">
{{headerTitle}}
</div>
</div>