WIP: refactor walletService
This commit is contained in:
parent
8e031a83ad
commit
601fa94fde
3 changed files with 426 additions and 476 deletions
|
|
@ -262,122 +262,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
|||
};
|
||||
|
||||
|
||||
|
||||
var _walletStatusHash = function(walletStatus) {
|
||||
var bal;
|
||||
if (walletStatus) {
|
||||
bal = walletStatus.balance.totalAmount;
|
||||
} else {
|
||||
bal = self.totalBalanceSat;
|
||||
}
|
||||
return bal;
|
||||
};
|
||||
|
||||
// TODO move this to wallet service
|
||||
self.updateAll = function(opts, initStatusHash, tries) {
|
||||
$scope.$broadcast('scroll.refreshComplete');
|
||||
tries = tries || 0;
|
||||
opts = opts || {};
|
||||
var fc = profileService.focusedClient;
|
||||
if (!fc) return;
|
||||
|
||||
var walletId = fc.credentials.walletId
|
||||
|
||||
if (opts.untilItChanges && lodash.isUndefined(initStatusHash)) {
|
||||
initStatusHash = _walletStatusHash();
|
||||
$log.debug('Updating status until it changes. initStatusHash:' + initStatusHash)
|
||||
}
|
||||
|
||||
var get = function(cb) {
|
||||
if (opts.walletStatus)
|
||||
return cb(null, opts.walletStatus);
|
||||
else {
|
||||
self.updateError = false;
|
||||
return fc.getStatus({
|
||||
twoStep: true
|
||||
}, function(err, ret) {
|
||||
if (err) {
|
||||
self.updateError = bwcError.msg(err, gettext('Could not update Wallet'));
|
||||
} else {
|
||||
self.isSingleAddress = !!ret.wallet.singleAddress;
|
||||
if (!opts.quiet)
|
||||
self.updating = ret.wallet.scanStatus == 'running';
|
||||
}
|
||||
return cb(err, ret);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// If not untilItChanges...trigger history update now
|
||||
if (opts.triggerTxUpdate && !opts.untilItChanges) {
|
||||
$timeout(function() {
|
||||
self.debounceUpdateHistory();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
|
||||
if (!opts.quiet)
|
||||
self.updating = true;
|
||||
|
||||
$log.debug('Updating Status:', fc.credentials.walletName, tries);
|
||||
get(function(err, walletStatus) {
|
||||
var currentStatusHash = _walletStatusHash(walletStatus);
|
||||
$log.debug('Status update. hash:' + currentStatusHash + ' Try:' + tries);
|
||||
if (!err && opts.untilItChanges && initStatusHash == currentStatusHash && tries < 7 && walletId == profileService.focusedClient.credentials.walletId) {
|
||||
return $timeout(function() {
|
||||
$log.debug('Retrying update... Try:' + tries)
|
||||
return self.updateAll({
|
||||
walletStatus: null,
|
||||
untilItChanges: true,
|
||||
triggerTxUpdate: opts.triggerTxUpdate,
|
||||
}, initStatusHash, ++tries);
|
||||
}, 1400 * tries);
|
||||
}
|
||||
|
||||
if (walletId != profileService.focusedClient.credentials.walletId)
|
||||
return;
|
||||
|
||||
self.updating = false;
|
||||
|
||||
if (err) {
|
||||
self.handleError(err);
|
||||
return;
|
||||
}
|
||||
$log.debug('Wallet Status:', walletStatus);
|
||||
self.setPendingTxps(walletStatus.pendingTxps);
|
||||
|
||||
// Status Shortcuts
|
||||
self.lastUpdate = Date.now();
|
||||
self.walletName = walletStatus.wallet.name;
|
||||
self.walletSecret = walletStatus.wallet.secret;
|
||||
self.walletStatus = walletStatus.wallet.status;
|
||||
self.walletScanStatus = walletStatus.wallet.scanStatus;
|
||||
self.copayers = walletStatus.wallet.copayers;
|
||||
self.preferences = walletStatus.preferences;
|
||||
self.setBalance(walletStatus.balance);
|
||||
self.otherWallets = lodash.filter(profileService.getWallets(self.network), function(w) {
|
||||
return w.id != self.walletId;
|
||||
});
|
||||
|
||||
// Notify external addons or plugins
|
||||
$rootScope.$emit('Local/BalanceUpdated', walletStatus.balance);
|
||||
$rootScope.$apply();
|
||||
|
||||
|
||||
if (opts.triggerTxUpdate && opts.untilItChanges) {
|
||||
$timeout(function() {
|
||||
self.debounceUpdateHistory();
|
||||
}, 1);
|
||||
} else {
|
||||
self.loadingWallet = false;
|
||||
}
|
||||
|
||||
if (opts.cb) return opts.cb();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
self.setSpendUnconfirmed = function(spendUnconfirmed) {
|
||||
self.spendUnconfirmed = spendUnconfirmed || configService.getSync().wallet.spendUnconfirmed;
|
||||
};
|
||||
|
|
@ -659,163 +543,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
|||
});
|
||||
}
|
||||
|
||||
self.getSavedTxs = function(walletId, cb) {
|
||||
|
||||
storageService.getTxHistory(walletId, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var localTxs = [];
|
||||
|
||||
if (!txs) {
|
||||
return cb(null, localTxs);
|
||||
}
|
||||
|
||||
try {
|
||||
localTxs = JSON.parse(txs);
|
||||
} catch (ex) {
|
||||
$log.warn(ex);
|
||||
}
|
||||
return cb(null, lodash.compact(localTxs));
|
||||
});
|
||||
}
|
||||
|
||||
self.updateLocalTxHistory = function(client, cb) {
|
||||
var FIRST_LIMIT = 5;
|
||||
var LIMIT = 50;
|
||||
var requestLimit = FIRST_LIMIT;
|
||||
var walletId = client.credentials.walletId;
|
||||
var config = configService.getSync().wallet.settings;
|
||||
|
||||
var fixTxsUnit = function(txs) {
|
||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||
|
||||
var cacheUnit = txs[0].amountStr.split(' ')[1];
|
||||
|
||||
if (cacheUnit == config.unitName)
|
||||
return;
|
||||
|
||||
var name = ' ' + config.unitName;
|
||||
|
||||
$log.debug('Fixing Tx Cache Unit to:' + name)
|
||||
lodash.each(txs, function(tx) {
|
||||
|
||||
tx.amountStr = profileService.formatAmount(tx.amount) + name;
|
||||
tx.feeStr = profileService.formatAmount(tx.fees) + name;
|
||||
});
|
||||
};
|
||||
|
||||
self.getSavedTxs(walletId, function(err, txsFromLocal) {
|
||||
if (err) return cb(err);
|
||||
|
||||
fixTxsUnit(txsFromLocal);
|
||||
|
||||
var confirmedTxs = self.removeAndMarkSoftConfirmedTx(txsFromLocal);
|
||||
var endingTxid = confirmedTxs[0] ? confirmedTxs[0].txid : null;
|
||||
var endingTs = confirmedTxs[0] ? confirmedTxs[0].time : null;
|
||||
|
||||
|
||||
// First update
|
||||
if (walletId == profileService.focusedClient.credentials.walletId) {
|
||||
self.completeHistory = txsFromLocal;
|
||||
self.setCompactTxHistory();
|
||||
}
|
||||
|
||||
if (historyUpdateInProgress[walletId])
|
||||
return;
|
||||
|
||||
historyUpdateInProgress[walletId] = true;
|
||||
|
||||
function getNewTxs(newTxs, skip, i_cb) {
|
||||
self.getTxsFromServer(client, skip, endingTxid, requestLimit, function(err, res, shouldContinue) {
|
||||
if (err) return i_cb(err);
|
||||
|
||||
newTxs = newTxs.concat(lodash.compact(res));
|
||||
skip = skip + requestLimit;
|
||||
|
||||
$log.debug('Syncing TXs. Got:' + newTxs.length + ' Skip:' + skip, ' EndingTxid:', endingTxid, ' Continue:', shouldContinue);
|
||||
|
||||
if (!shouldContinue) {
|
||||
newTxs = self.processNewTxs(newTxs);
|
||||
$log.debug('Finished Sync: New / soft confirmed Txs: ' + newTxs.length);
|
||||
return i_cb(null, newTxs);
|
||||
}
|
||||
|
||||
requestLimit = LIMIT;
|
||||
getNewTxs(newTxs, skip, i_cb);
|
||||
|
||||
// Progress update
|
||||
if (walletId == profileService.focusedClient.credentials.walletId) {
|
||||
self.txProgress = newTxs.length;
|
||||
if (self.completeHistory < FIRST_LIMIT && txsFromLocal.length == 0) {
|
||||
$log.debug('Showing partial history');
|
||||
var newHistory = self.processNewTxs(newTxs);
|
||||
newHistory = lodash.compact(newHistory.concat(confirmedTxs));
|
||||
self.completeHistory = newHistory;
|
||||
self.setCompactTxHistory();
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$apply();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getNewTxs([], 0, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
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);
|
||||
client.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();
|
||||
});
|
||||
}
|
||||
|
||||
updateNotes(function() {
|
||||
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 == profileService.focusedClient.credentials.walletId) {
|
||||
self.completeHistory = newHistory;
|
||||
self.setCompactTxHistory();
|
||||
}
|
||||
|
||||
return storageService.setTxHistory(historyToSave, walletId, function() {
|
||||
$log.debug('Tx History saved.');
|
||||
|
||||
return cb();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
self.showMore = function() {
|
||||
$timeout(function() {
|
||||
|
|
@ -835,181 +562,8 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
|||
}, 100);
|
||||
};
|
||||
|
||||
self.startSearch = function() {
|
||||
self.isSearching = true;
|
||||
self.txHistorySearchResults = [];
|
||||
self.result = [];
|
||||
self.historyShowMore = false;
|
||||
self.nextTxHistory = self.historyShowMoreLimit;
|
||||
}
|
||||
|
||||
self.cancelSearch = function() {
|
||||
self.isSearching = false;
|
||||
self.result = [];
|
||||
self.setCompactTxHistory();
|
||||
}
|
||||
|
||||
self.updateSearchInput = function(search) {
|
||||
self.search = search;
|
||||
if (isCordova)
|
||||
window.plugins.toast.hide();
|
||||
self.throttleSearch();
|
||||
$ionicScrollDelegate.resize();
|
||||
}
|
||||
|
||||
self.throttleSearch = lodash.throttle(function() {
|
||||
|
||||
function filter(search) {
|
||||
self.result = [];
|
||||
|
||||
function computeSearchableString(tx) {
|
||||
var addrbook = '';
|
||||
if (tx.addressTo && self.addressbook && self.addressbook[tx.addressTo]) addrbook = self.addressbook[tx.addressTo] || '';
|
||||
var searchableDate = computeSearchableDate(new Date(tx.time * 1000));
|
||||
var message = tx.message ? tx.message : '';
|
||||
var comment = tx.note ? tx.note.body : '';
|
||||
var addressTo = tx.addressTo ? tx.addressTo : '';
|
||||
return ((tx.amountStr + message + addressTo + addrbook + searchableDate + comment).toString()).toLowerCase();
|
||||
}
|
||||
|
||||
function computeSearchableDate(date) {
|
||||
var day = ('0' + date.getDate()).slice(-2).toString();
|
||||
var month = ('0' + (date.getMonth() + 1)).slice(-2).toString();
|
||||
var year = date.getFullYear();
|
||||
return [month, day, year].join('/');
|
||||
};
|
||||
|
||||
if (lodash.isEmpty(search)) {
|
||||
self.historyShowMore = false;
|
||||
return [];
|
||||
}
|
||||
self.result = lodash.filter(self.completeHistory, function(tx) {
|
||||
if (!tx.searcheableString) tx.searcheableString = computeSearchableString(tx);
|
||||
return lodash.includes(tx.searcheableString, search.toLowerCase());
|
||||
});
|
||||
|
||||
if (self.result.length > self.historyShowLimit) self.historyShowMore = true;
|
||||
else self.historyShowMore = false;
|
||||
|
||||
return self.result;
|
||||
};
|
||||
|
||||
self.txHistorySearchResults = filter(self.search).slice(0, self.historyShowLimit);
|
||||
if (isCordova)
|
||||
window.plugins.toast.showShortBottom(gettextCatalog.getString('Matches: ' + self.result.length));
|
||||
|
||||
$timeout(function() {
|
||||
$rootScope.$apply();
|
||||
});
|
||||
|
||||
}, 1000);
|
||||
|
||||
self.getTxsFromServer = function(client, skip, endingTxid, limit, cb) {
|
||||
var res = [];
|
||||
|
||||
client.getTxHistory({
|
||||
skip: skip,
|
||||
limit: limit
|
||||
}, function(err, txsFromServer) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (!txsFromServer.length)
|
||||
return cb();
|
||||
|
||||
var res = lodash.takeWhile(txsFromServer, function(tx) {
|
||||
return tx.txid != endingTxid;
|
||||
});
|
||||
|
||||
return cb(null, res, res.length == limit);
|
||||
});
|
||||
};
|
||||
|
||||
self.updateHistory = function() {
|
||||
var fc = profileService.focusedClient;
|
||||
if (!fc) return;
|
||||
var walletId = fc.credentials.walletId;
|
||||
|
||||
if (!fc.isComplete()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$log.debug('Updating Transaction History');
|
||||
self.txHistoryError = false;
|
||||
self.updatingTxHistory = true;
|
||||
|
||||
$timeout(function() {
|
||||
self.updateLocalTxHistory(fc, function(err) {
|
||||
historyUpdateInProgress[walletId] = self.updatingTxHistory = false;
|
||||
self.loadingWallet = false;
|
||||
self.txProgress = 0;
|
||||
if (err)
|
||||
self.txHistoryError = true;
|
||||
|
||||
$timeout(function() {
|
||||
self.newTx = false
|
||||
}, 1000);
|
||||
|
||||
$rootScope.$apply();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
self.setCompactTxHistory = function() {
|
||||
self.isSearching = false;
|
||||
self.nextTxHistory = self.historyShowMoreLimit;
|
||||
self.txHistory = self.completeHistory ? self.completeHistory.slice(0, self.historyShowLimit) : null;
|
||||
self.historyShowMore = self.completeHistory ? self.completeHistory.length > self.historyShowLimit : null;
|
||||
};
|
||||
|
||||
self.debounceUpdateHistory = lodash.debounce(function() {
|
||||
self.updateHistory();
|
||||
}, 1000);
|
||||
|
||||
self.throttledUpdateHistory = lodash.throttle(function() {
|
||||
self.updateHistory();
|
||||
}, 5000);
|
||||
|
||||
self.showErrorPopup = function(msg, cb) {
|
||||
$log.warn('Showing err popup:' + msg);
|
||||
|
||||
function openErrorPopup(msg, cb) {
|
||||
$scope.msg = msg;
|
||||
|
||||
self.errorPopup = $ionicPopup.show({
|
||||
templateUrl: 'views/includes/alert.html',
|
||||
scope: $scope,
|
||||
});
|
||||
|
||||
$scope.close = function() {
|
||||
return cb();
|
||||
};
|
||||
}
|
||||
|
||||
openErrorPopup(msg, function() {
|
||||
self.errorPopup.close();
|
||||
if (cb) return cb();
|
||||
});
|
||||
};
|
||||
|
||||
self.recreate = function(cb) {
|
||||
var fc = profileService.focusedClient;
|
||||
ongoingProcess.set('recreating', true);
|
||||
fc.recreateWallet(function(err) {
|
||||
self.notAuthorized = false;
|
||||
ongoingProcess.set('recreating', false);
|
||||
|
||||
if (err) {
|
||||
self.handleError(err);
|
||||
$rootScope.$apply();
|
||||
return;
|
||||
}
|
||||
|
||||
profileService.bindWalletClient(fc, {
|
||||
force: true
|
||||
});
|
||||
self.startScan(self.walletId);
|
||||
});
|
||||
};
|
||||
|
||||
self.toggleLeftMenu = function() {
|
||||
profileService.isDisclaimerAccepted(function(val) {
|
||||
|
|
@ -1019,30 +573,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
|||
});
|
||||
};
|
||||
|
||||
self.retryScan = function() {
|
||||
var self = this;
|
||||
self.startScan(self.walletId);
|
||||
}
|
||||
|
||||
self.startScan = function(walletId) {
|
||||
$log.debug('Scanning wallet ' + walletId);
|
||||
var c = profileService.walletClients[walletId];
|
||||
if (!c.isComplete()) return;
|
||||
|
||||
if (self.walletId == walletId)
|
||||
self.updating = true;
|
||||
|
||||
c.startScan({
|
||||
includeCopayerBranches: true,
|
||||
}, function(err) {
|
||||
if (err && self.walletId == walletId) {
|
||||
self.updating = false;
|
||||
self.handleError(err);
|
||||
$rootScope.$apply();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
self.initGlidera = function(accessToken) {
|
||||
self.glideraEnabled = configService.getSync().glidera.enabled;
|
||||
self.glideraTestnet = configService.getSync().glidera.testnet;
|
||||
|
|
@ -1656,6 +1186,11 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
|||
});
|
||||
|
||||
$rootScope.$on('Local/NewFocusedWallet', function() {
|
||||
console.log('[index.js.1200:NewFocusedWallet:] TODO'); //TODO
|
||||
|
||||
return;
|
||||
|
||||
|
||||
uxLanguage.update();
|
||||
self.setFocusedWallet();
|
||||
self.updateHistory();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
// DO NOT INCLUDE STORAGE HERE \/ \/
|
||||
angular.module('copayApp.services').factory('walletService', function($log, lodash, trezor, ledger, storageService, configService, uxLanguage) {
|
||||
// DO NOT INCLUDE STORAGE HERE ^^
|
||||
|
||||
angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, storageService, configService, uxLanguage) {
|
||||
// DO NOT INCLUDE STORAGE HERE ^^
|
||||
|
||||
var root = {};
|
||||
|
||||
var _signWithLedger = function(client, txp, cb) {
|
||||
|
|
@ -42,6 +42,345 @@ angular.module('copayApp.services').factory('walletService', function($log, loda
|
|||
return true;
|
||||
};
|
||||
|
||||
var _walletStatusHash = function(walletStatus) {
|
||||
var bal;
|
||||
if (walletStatus) {
|
||||
bal = walletStatus.balance.totalAmount;
|
||||
} else {
|
||||
bal = self.totalBalanceSat;
|
||||
}
|
||||
return bal;
|
||||
};
|
||||
|
||||
|
||||
// TODO
|
||||
// This handles errors from BWS/index which normally
|
||||
// trigger from async events (like updates).
|
||||
// Debounce function avoids multiple popups
|
||||
var _handleError = function(err) {
|
||||
$log.warn('Client ERROR: ', err);
|
||||
|
||||
$log.warn('TODO');
|
||||
return ; // TODO!!!
|
||||
if (err instanceof errors.NOT_AUTHORIZED) {
|
||||
self.notAuthorized = true;
|
||||
go.walletHome();
|
||||
} else if (err instanceof errors.NOT_FOUND) {
|
||||
self.showErrorPopup(gettext('Could not access Wallet Service: Not found'));
|
||||
} else {
|
||||
var msg = ""
|
||||
$scope.$emit('Local/ClientError', (err.error ? err.error : err));
|
||||
var msg = bwcError.msg(err, gettext('Error at Wallet Service'));
|
||||
self.showErrorPopup(msg);
|
||||
}
|
||||
};
|
||||
root.handleError = lodash.debounce(_handleError, 1000);
|
||||
|
||||
// emits
|
||||
// statusUpdated walletId, err ,statusObj
|
||||
//
|
||||
root.updateStatus = function(client, opts, cb, initStatusHash, tries) {
|
||||
tries = tries || 0;
|
||||
opts = opts || {};
|
||||
|
||||
var walletId = client.credentials.walletId
|
||||
|
||||
if (opts.untilItChanges && lodash.isUndefined(initStatusHash)) {
|
||||
initStatusHash = _walletStatusHash();
|
||||
$log.debug('Updating status until it changes. initStatusHash:' + initStatusHash)
|
||||
}
|
||||
|
||||
var get = function(cb) {
|
||||
if (opts.walletStatus)
|
||||
return cb(null, opts.walletStatus);
|
||||
else {
|
||||
return client.getStatus({
|
||||
twoStep: true
|
||||
}, function(err, ret) {
|
||||
if (err)
|
||||
return cb(bwcError.msg(err, gettext('Could not update Wallet')));
|
||||
// TODO??
|
||||
// self.isSingleAddress = !!ret.wallet.singleAddress;
|
||||
// self.updating = ret.wallet.scanStatus == 'running';
|
||||
return cb(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// If not untilItChanges...trigger history update now
|
||||
if (opts.triggerTxUpdate && !opts.untilItChanges) {
|
||||
$timeout(function() {
|
||||
root.debounceUpdateHistory();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
|
||||
// if (!opts.quiet)
|
||||
// self.updating = true;
|
||||
|
||||
$log.debug('Updating Status:', client.credentials.walletName, tries);
|
||||
get(function(err, walletStatus) {
|
||||
var currentStatusHash = _walletStatusHash(walletStatus);
|
||||
$log.debug('Status update. hash:' + currentStatusHash + ' Try:' + tries);
|
||||
if (!err && opts.untilItChanges && initStatusHash == currentStatusHash && tries < 7 && walletId == profileService.focusedClient.credentials.walletId) {
|
||||
return $timeout(function() {
|
||||
$log.debug('Retrying update... ' + walletId + ' Try:' + tries)
|
||||
return root.updateStatus(client, {
|
||||
walletStatus: null,
|
||||
untilItChanges: true,
|
||||
triggerTxUpdate: opts.triggerTxUpdate,
|
||||
}, cb, initStatusHash, ++tries);
|
||||
}, 1400 * tries);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
root.handleError(err);
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
$log.debug('Wallet Status:' + client.credentials.walletName, walletStatus);
|
||||
|
||||
// self.setPendingTxps(walletStatus.pendingTxps);
|
||||
//
|
||||
// // Status Shortcuts
|
||||
// self.lastUpdate = Date.now();
|
||||
// self.walletName = walletStatus.wallet.name;
|
||||
// self.walletSecret = walletStatus.wallet.secret;
|
||||
// self.walletStatus = walletStatus.wallet.status;
|
||||
// self.walletScanStatus = walletStatus.wallet.scanStatus;
|
||||
// self.copayers = walletStatus.wallet.copayers;
|
||||
// self.preferences = walletStatus.preferences;
|
||||
// self.setBalance(walletStatus.balance);
|
||||
// self.otherWallets = lodash.filter(profileService.getWallets(self.network), function(w) {
|
||||
// return w.id != self.walletId;
|
||||
// });
|
||||
//
|
||||
// Notify external addons or plugins
|
||||
|
||||
// TODO
|
||||
if (opts.triggerTxUpdate && opts.untilItChanges) {
|
||||
$timeout(function() {
|
||||
root.debounceUpdateHistory();
|
||||
}, 1);
|
||||
}
|
||||
return cb(null, walletStatus);
|
||||
// } else {
|
||||
// self.loadingWallet = false;
|
||||
// }
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var getSavedTxs = function(walletId, cb) {
|
||||
|
||||
storageService.getTxHistory(walletId, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var localTxs = [];
|
||||
|
||||
if (!txs) {
|
||||
return cb(null, localTxs);
|
||||
}
|
||||
|
||||
try {
|
||||
localTxs = JSON.parse(txs);
|
||||
} catch (ex) {
|
||||
$log.warn(ex);
|
||||
}
|
||||
return cb(null, lodash.compact(localTxs));
|
||||
});
|
||||
};
|
||||
|
||||
var getTxsFromServer = function(client, skip, endingTxid, limit, cb) {
|
||||
var res = [];
|
||||
|
||||
client.getTxHistory({
|
||||
skip: skip,
|
||||
limit: limit
|
||||
}, function(err, txsFromServer) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (!txsFromServer.length)
|
||||
return cb();
|
||||
|
||||
var res = lodash.takeWhile(txsFromServer, function(tx) {
|
||||
return tx.txid != endingTxid;
|
||||
});
|
||||
|
||||
return cb(null, res, res.length == limit);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var updateLocalTxHistory = function(client, cb) {
|
||||
var FIRST_LIMIT = 5;
|
||||
var LIMIT = 50;
|
||||
var requestLimit = FIRST_LIMIT;
|
||||
var walletId = client.credentials.walletId;
|
||||
var config = configService.getSync().wallet.settings;
|
||||
|
||||
var fixTxsUnit = function(txs) {
|
||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||
|
||||
var cacheUnit = txs[0].amountStr.split(' ')[1];
|
||||
|
||||
if (cacheUnit == config.unitName)
|
||||
return;
|
||||
|
||||
var name = ' ' + config.unitName;
|
||||
|
||||
$log.debug('Fixing Tx Cache Unit to:' + name)
|
||||
lodash.each(txs, function(tx) {
|
||||
|
||||
tx.amountStr = profileService.formatAmount(tx.amount) + name;
|
||||
tx.feeStr = profileService.formatAmount(tx.fees) + name;
|
||||
});
|
||||
};
|
||||
|
||||
getSavedTxs(walletId, function(err, txsFromLocal) {
|
||||
if (err) return cb(err);
|
||||
|
||||
fixTxsUnit(txsFromLocal);
|
||||
|
||||
var confirmedTxs = self.removeAndMarkSoftConfirmedTx(txsFromLocal);
|
||||
var endingTxid = confirmedTxs[0] ? confirmedTxs[0].txid : null;
|
||||
var endingTs = confirmedTxs[0] ? confirmedTxs[0].time : null;
|
||||
|
||||
|
||||
// First update
|
||||
if (walletId == profileService.focusedClient.credentials.walletId) {
|
||||
self.completeHistory = txsFromLocal;
|
||||
setCompactTxHistory();
|
||||
}
|
||||
|
||||
if (historyUpdateInProgress[walletId])
|
||||
return;
|
||||
|
||||
historyUpdateInProgress[walletId] = true;
|
||||
|
||||
function getNewTxs(newTxs, skip, i_cb) {
|
||||
getTxsFromServer(client, skip, endingTxid, requestLimit, function(err, res, shouldContinue) {
|
||||
if (err) return i_cb(err);
|
||||
|
||||
newTxs = newTxs.concat(lodash.compact(res));
|
||||
skip = skip + requestLimit;
|
||||
|
||||
$log.debug('Syncing TXs. Got:' + newTxs.length + ' Skip:' + skip, ' EndingTxid:', endingTxid, ' Continue:', shouldContinue);
|
||||
|
||||
if (!shouldContinue) {
|
||||
newTxs = self.processNewTxs(newTxs);
|
||||
$log.debug('Finished Sync: New / soft confirmed Txs: ' + newTxs.length);
|
||||
return i_cb(null, newTxs);
|
||||
}
|
||||
|
||||
requestLimit = LIMIT;
|
||||
getNewTxs(newTxs, skip, i_cb);
|
||||
|
||||
// Progress update
|
||||
if (walletId == profileService.focusedClient.credentials.walletId) {
|
||||
self.txProgress = newTxs.length;
|
||||
if (self.completeHistory < FIRST_LIMIT && txsFromLocal.length == 0) {
|
||||
$log.debug('Showing partial history');
|
||||
var newHistory = self.processNewTxs(newTxs);
|
||||
newHistory = lodash.compact(newHistory.concat(confirmedTxs));
|
||||
self.completeHistory = newHistory;
|
||||
setCompactTxHistory();
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$apply();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getNewTxs([], 0, function(err, txs) {
|
||||
if (err) return cb(err);
|
||||
|
||||
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);
|
||||
client.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();
|
||||
});
|
||||
}
|
||||
|
||||
updateNotes(function() {
|
||||
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 == profileService.focusedClient.credentials.walletId) {
|
||||
self.completeHistory = newHistory;
|
||||
setCompactTxHistory();
|
||||
}
|
||||
|
||||
return storageService.setTxHistory(historyToSave, walletId, function() {
|
||||
$log.debug('Tx History saved.');
|
||||
|
||||
return cb();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
root.updateHistory = function(client) {
|
||||
var walletId = client.credentials.walletId;
|
||||
|
||||
if (!client.isComplete()) return;
|
||||
|
||||
|
||||
$log.debug('Updating Transaction History');
|
||||
self.txHistoryError = false;
|
||||
self.updatingTxHistory = true;
|
||||
|
||||
$timeout(function() {
|
||||
updateLocalTxHistory(client, function(err) {
|
||||
historyUpdateInProgress[walletId] = self.updatingTxHistory = false;
|
||||
self.loadingWallet = false;
|
||||
self.txProgress = 0;
|
||||
if (err)
|
||||
self.txHistoryError = true;
|
||||
|
||||
$timeout(function() {
|
||||
self.newTx = false
|
||||
}, 1000);
|
||||
|
||||
$rootScope.$apply();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
root.isEncrypted = function(client) {
|
||||
if (lodash.isEmpty(client)) return;
|
||||
|
|
@ -225,5 +564,84 @@ angular.module('copayApp.services').factory('walletService', function($log, loda
|
|||
});
|
||||
};
|
||||
|
||||
var setCompactTxHistory = function() {
|
||||
|
||||
// TODO
|
||||
self.isSearching = false;
|
||||
self.nextTxHistory = self.historyShowMoreLimit;
|
||||
self.txHistory = self.completeHistory ? self.completeHistory.slice(0, self.historyShowLimit) : null;
|
||||
self.historyShowMore = self.completeHistory ? self.completeHistory.length > self.historyShowLimit : null;
|
||||
};
|
||||
|
||||
root.debounceUpdateHistory = lodash.debounce(function() {
|
||||
root.updateHistory();
|
||||
}, 1000);
|
||||
|
||||
self.throttledUpdateHistory = lodash.throttle(function() {
|
||||
root.updateHistory();
|
||||
}, 5000);
|
||||
|
||||
self.showErrorPopup = function(msg, cb) {
|
||||
$log.warn('Showing err popup:' + msg);
|
||||
|
||||
function openErrorPopup(msg, cb) {
|
||||
$scope.msg = msg;
|
||||
|
||||
self.errorPopup = $ionicPopup.show({
|
||||
templateUrl: 'views/includes/alert.html',
|
||||
scope: $scope,
|
||||
});
|
||||
|
||||
$scope.close = function() {
|
||||
return cb();
|
||||
};
|
||||
}
|
||||
|
||||
openErrorPopup(msg, function() {
|
||||
self.errorPopup.close();
|
||||
if (cb) return cb();
|
||||
});
|
||||
};
|
||||
|
||||
root.recreate = function(client, cb) {
|
||||
ongoingProcess.set('recreating', true);
|
||||
client.recreateWallet(function(err) {
|
||||
self.notAuthorized = false;
|
||||
ongoingProcess.set('recreating', false);
|
||||
|
||||
if (err) {
|
||||
self.handleError(err);
|
||||
$rootScope.$apply();
|
||||
return;
|
||||
}
|
||||
|
||||
profileService.bindWalletClient(client, {
|
||||
force: true
|
||||
});
|
||||
self.startScan(client);
|
||||
});
|
||||
};
|
||||
|
||||
root.startScan = function(client) {
|
||||
$log.debug('Scanning wallet ' + client.credentials.walletId);
|
||||
if (!client.isComplete()) return;
|
||||
|
||||
// self.updating = true;
|
||||
|
||||
client.startScan({
|
||||
includeCopayerBranches: true,
|
||||
}, function(err) {
|
||||
|
||||
// TODO
|
||||
// if (err && self.walletId == walletId) {
|
||||
// self.updating = false;
|
||||
// self.handleError(err);
|
||||
// $rootScope.$apply();
|
||||
// }
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue