2015-03-06 07:00:10 -08:00
|
|
|
'use strict';
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, $ionicScrollDelegate, $ionicPopup, latestReleaseService, feeService, bwcService, pushNotificationsService, lodash, go, profileService, configService, rateService, storageService, addressService, gettext, gettextCatalog, amMoment, addonManager, bwsError, txFormatService, uxLanguage, glideraService, coinbaseService, platformInfo, addressbookService, openURLService, ongoingProcess) {
|
2015-03-06 07:00:10 -08:00
|
|
|
var self = this;
|
2015-10-23 09:26:59 -07:00
|
|
|
var SOFT_CONFIRMATION_LIMIT = 12;
|
2016-01-22 13:16:50 -08:00
|
|
|
var errors = bwcService.getErrors();
|
2016-02-18 12:16:07 -08:00
|
|
|
var historyUpdateInProgress = {};
|
2016-05-31 10:55:08 -07:00
|
|
|
var isChromeApp = platformInfo.isChromeApp;
|
|
|
|
var isCordova = platformInfo.isCordova;
|
2016-05-31 12:52:38 -07:00
|
|
|
var isNW = platformInfo.isNW;
|
2016-02-18 12:16:07 -08:00
|
|
|
|
|
|
|
var ret = {};
|
|
|
|
ret.isCordova = isCordova;
|
|
|
|
ret.isChromeApp = isChromeApp;
|
2016-05-31 10:55:08 -07:00
|
|
|
ret.isSafari = platformInfo.isSafari;
|
|
|
|
ret.isWindowsPhoneApp = platformInfo.isWP;
|
2016-02-18 12:16:07 -08:00
|
|
|
ret.historyShowLimit = 10;
|
2016-05-17 07:10:16 -07:00
|
|
|
ret.historyShowMoreLimit = 10;
|
2016-02-23 05:52:20 -08:00
|
|
|
ret.isSearching = false;
|
2016-02-18 12:16:07 -08:00
|
|
|
ret.prevState = 'walletHome';
|
|
|
|
|
|
|
|
ret.menu = [{
|
2015-04-29 15:19:10 -07:00
|
|
|
'title': gettext('Receive'),
|
2016-01-15 06:59:29 -08:00
|
|
|
'icon': {
|
|
|
|
false: 'icon-receive',
|
|
|
|
true: 'icon-receive-active'
|
|
|
|
},
|
2015-04-21 22:48:00 -07:00
|
|
|
'link': 'receive'
|
2015-12-02 13:20:22 -08:00
|
|
|
}, {
|
2015-12-04 10:43:17 -08:00
|
|
|
'title': gettext('Activity'),
|
2016-01-15 06:59:29 -08:00
|
|
|
'icon': {
|
|
|
|
false: 'icon-activity',
|
|
|
|
true: 'icon-activity-active'
|
|
|
|
},
|
2015-12-02 13:20:22 -08:00
|
|
|
'link': 'walletHome'
|
2015-04-21 22:48:00 -07:00
|
|
|
}, {
|
2015-04-29 15:19:10 -07:00
|
|
|
'title': gettext('Send'),
|
2016-01-15 06:59:29 -08:00
|
|
|
'icon': {
|
|
|
|
false: 'icon-send',
|
|
|
|
true: 'icon-send-active'
|
|
|
|
},
|
2015-04-21 22:48:00 -07:00
|
|
|
'link': 'send'
|
2015-04-23 11:19:30 -07:00
|
|
|
}];
|
2015-04-21 22:48:00 -07:00
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
ret.addonViews = addonManager.addonViews();
|
|
|
|
ret.txTemplateUrl = addonManager.txTemplateUrl() || 'views/includes/transaction.html';
|
Addon support
Addons are simple Angular modules with views, controllers, services etc. Addons can register
themselves in Copay using pluginManagerProvider. It allows them to add extra items to the bottom
menu and as well as extra tab-views:
````
addonManagerProvider.registerAddon({
menuItem: {
'title': 'Assets',
'icon': 'icon-pricetag',
'link': 'assets'
},
view: {
id: 'assets',
'class': 'assets',
template: 'colored-coins/views/assets.html'
}
});
````
Addons can consume core Copay services and listen for events to react on changes. For this very
first addon system inplementation Copay emits additional BalanceUpdated event so that interested
addons can react on new transactions (see plugin reference implementation below).
As bottom menu can accomodate only 6 items without sacrificing usability, so it was reworked to
have second layer of items. Now If menu has more than 6 items, toggle button will be added to
the menu allowing to reveal extra items in a sliding panel. Bottom menu in this case will show
only 5 items, the rest will be rendered on sliding panel.
This changes addresses issue #2949 and reference implementation of addon could be found here:
https://github.com/troggy/copay-colored-coins-plugin
2015-07-04 03:02:46 -07:00
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
ret.tab = 'walletHome';
|
|
|
|
var vanillaScope = ret;
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2016-05-31 12:52:38 -07:00
|
|
|
if (isNW) {
|
2016-04-11 08:56:18 -07:00
|
|
|
latestReleaseService.checkLatestRelease(function(err, newRelease) {
|
|
|
|
if (err) {
|
|
|
|
$log.warn(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newRelease)
|
|
|
|
$scope.newRelease = gettext('There is a new version of Copay. Please update');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
function strip(number) {
|
|
|
|
return (parseFloat(number.toPrecision(12)));
|
|
|
|
};
|
|
|
|
|
|
|
|
self.goHome = function() {
|
|
|
|
go.walletHome();
|
|
|
|
};
|
2015-07-30 11:26:16 -07:00
|
|
|
|
2016-05-13 11:05:43 -07:00
|
|
|
self.hideBalance = function() {
|
|
|
|
storageService.getHideBalanceFlag(self.walletId, function(err, shouldHideBalance) {
|
2016-05-20 07:37:13 -07:00
|
|
|
if (err) self.shouldHideBalance = false;
|
|
|
|
else self.shouldHideBalance = (shouldHideBalance == 'true') ? true : false;
|
2016-05-13 11:05:43 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-05-20 07:37:13 -07:00
|
|
|
self.onHold = function() {
|
|
|
|
self.shouldHideBalance = !self.shouldHideBalance;
|
|
|
|
storageService.setHideBalanceFlag(self.walletId, self.shouldHideBalance, function() {});
|
2016-05-13 11:05:43 -07:00
|
|
|
}
|
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
self.cleanInstance = function() {
|
|
|
|
$log.debug('Cleaning Index Instance');
|
|
|
|
lodash.each(self, function(v, k) {
|
|
|
|
if (lodash.isFunction(v)) return;
|
|
|
|
// This are to prevent flicker in mobile:
|
|
|
|
if (k == 'hasProfile') return;
|
2016-02-23 05:33:40 -08:00
|
|
|
if (k == 'tab') return;
|
2016-02-18 12:16:07 -08:00
|
|
|
if (k == 'noFocusedWallet') return;
|
|
|
|
if (k == 'backgroundColor') return;
|
|
|
|
if (k == 'loadingWallet') {
|
|
|
|
self.loadingWallet = true;
|
|
|
|
return;
|
|
|
|
}
|
2016-04-29 08:14:09 -07:00
|
|
|
if (!lodash.isUndefined(vanillaScope[k])) {
|
2016-02-23 05:33:40 -08:00
|
|
|
self[k] = vanillaScope[k];
|
|
|
|
return;
|
|
|
|
}
|
2016-02-18 12:16:07 -08:00
|
|
|
|
|
|
|
delete self[k];
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.setFocusedWallet = function() {
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
if (!fc) return;
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.clear();
|
2016-02-18 12:16:07 -08:00
|
|
|
self.cleanInstance();
|
2015-12-03 12:44:02 -08:00
|
|
|
self.loadingWallet = true;
|
2015-08-11 13:45:57 -07:00
|
|
|
self.setSpendUnconfirmed();
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
$timeout(function() {
|
2015-11-11 11:23:56 -08:00
|
|
|
$rootScope.$apply();
|
2016-06-13 07:44:58 -07:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.hasProfile = true;
|
2016-06-07 06:37:06 -07:00
|
|
|
self.isSingleAddress = false;
|
2015-03-06 07:00:10 -08:00
|
|
|
self.noFocusedWallet = false;
|
|
|
|
|
2015-04-29 08:16:28 -07:00
|
|
|
// Credentials Shortcuts
|
2015-03-06 07:00:10 -08:00
|
|
|
self.m = fc.credentials.m;
|
|
|
|
self.n = fc.credentials.n;
|
|
|
|
self.network = fc.credentials.network;
|
|
|
|
self.copayerId = fc.credentials.copayerId;
|
|
|
|
self.copayerName = fc.credentials.copayerName;
|
|
|
|
self.requiresMultipleSignatures = fc.credentials.m > 1;
|
|
|
|
self.isShared = fc.credentials.n > 1;
|
|
|
|
self.walletName = fc.credentials.walletName;
|
|
|
|
self.walletId = fc.credentials.walletId;
|
|
|
|
self.isComplete = fc.isComplete();
|
2015-07-15 18:10:59 -07:00
|
|
|
self.canSign = fc.canSign();
|
2015-09-04 06:17:59 -07:00
|
|
|
self.isPrivKeyExternal = fc.isPrivKeyExternal();
|
2015-11-07 06:06:12 -08:00
|
|
|
self.isPrivKeyEncrypted = fc.isPrivKeyEncrypted();
|
2015-09-04 06:17:59 -07:00
|
|
|
self.externalSource = fc.getPrivKeyExternalSourceName();
|
2015-11-04 10:45:33 -08:00
|
|
|
self.account = fc.credentials.account;
|
2016-05-20 06:02:44 -07:00
|
|
|
self.incorrectDerivation = fc.incorrectDerivation;
|
2015-11-04 10:45:33 -08:00
|
|
|
|
|
|
|
if (self.externalSource == 'trezor')
|
|
|
|
self.account++;
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.txps = [];
|
|
|
|
self.copayers = [];
|
2015-04-28 16:13:28 -07:00
|
|
|
self.updateColor();
|
2015-05-14 06:39:22 -07:00
|
|
|
self.updateAlias();
|
2015-10-30 14:34:34 -07:00
|
|
|
self.setAddressbook();
|
2015-09-15 05:41:42 -07:00
|
|
|
|
2015-10-05 08:20:00 -07:00
|
|
|
self.initGlidera();
|
2016-04-13 10:08:03 -07:00
|
|
|
self.initCoinbase();
|
2015-03-06 07:00:10 -08:00
|
|
|
|
2016-05-13 11:05:43 -07:00
|
|
|
self.hideBalance();
|
|
|
|
|
2015-12-10 09:52:42 -08:00
|
|
|
self.setCustomBWSFlag();
|
2016-03-09 06:53:47 -08:00
|
|
|
|
|
|
|
if (!self.isComplete) {
|
|
|
|
$log.debug('Wallet not complete BEFORE update... redirecting');
|
|
|
|
go.path('copayers');
|
|
|
|
} else {
|
2016-05-20 07:50:55 -07:00
|
|
|
if (go.is('copayers')) {
|
2016-03-09 06:53:47 -08:00
|
|
|
$log.debug('Wallet Complete BEFORE update... redirect to home');
|
|
|
|
go.walletHome();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-06 14:26:45 -07:00
|
|
|
profileService.needsBackup(fc, function(needsBackup) {
|
2016-02-16 09:37:34 -08:00
|
|
|
self.needsBackup = needsBackup;
|
2016-03-09 06:53:47 -08:00
|
|
|
self.openWallet(function() {
|
|
|
|
if (!self.isComplete) {
|
|
|
|
$log.debug('Wallet not complete after update... redirecting');
|
|
|
|
go.path('copayers');
|
|
|
|
} else {
|
2016-05-20 07:50:55 -07:00
|
|
|
if (go.is('copayers')) {
|
2016-03-09 06:53:47 -08:00
|
|
|
$log.debug('Wallet Complete after update... redirect to home');
|
|
|
|
go.walletHome();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2016-02-16 09:37:34 -08:00
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-11-10 15:05:05 -08:00
|
|
|
self.setCustomBWSFlag = function() {
|
|
|
|
var defaults = configService.getDefaults();
|
|
|
|
var config = configService.getSync();
|
|
|
|
|
2015-11-17 06:10:09 -08:00
|
|
|
self.usingCustomBWS = config.bwsFor && config.bwsFor[self.walletId] && (config.bwsFor[self.walletId] != defaults.bws.url);
|
2015-11-10 15:05:05 -08:00
|
|
|
};
|
|
|
|
|
2015-12-05 15:50:31 -08:00
|
|
|
|
2015-09-10 08:17:24 -07:00
|
|
|
self.setTab = function(tab, reset, tries, switchState) {
|
2015-04-28 16:13:28 -07:00
|
|
|
tries = tries || 0;
|
2015-08-08 05:25:40 -07:00
|
|
|
|
2015-09-10 08:17:24 -07:00
|
|
|
// check if the whole menu item passed
|
|
|
|
if (typeof tab == 'object') {
|
|
|
|
if (tab.open) {
|
|
|
|
if (tab.link) {
|
|
|
|
self.tab = tab.link;
|
|
|
|
}
|
|
|
|
tab.open();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
return self.setTab(tab.link, reset, tries, switchState);
|
|
|
|
}
|
|
|
|
}
|
2015-04-28 16:13:28 -07:00
|
|
|
if (self.tab === tab && !reset)
|
2015-04-23 12:17:18 -07:00
|
|
|
return;
|
|
|
|
|
2015-05-04 08:23:43 -07:00
|
|
|
if (!document.getElementById('menu-' + tab) && ++tries < 5) {
|
2015-04-28 16:13:28 -07:00
|
|
|
return $timeout(function() {
|
2015-09-10 08:17:24 -07:00
|
|
|
self.setTab(tab, reset, tries, switchState);
|
2015-04-28 16:13:28 -07:00
|
|
|
}, 300);
|
|
|
|
}
|
|
|
|
|
2016-05-24 11:58:59 -07:00
|
|
|
if (!self.tab || !go.is('walletHome'))
|
2015-04-23 12:17:18 -07:00
|
|
|
self.tab = 'walletHome';
|
|
|
|
|
2015-09-10 08:17:24 -07:00
|
|
|
var changeTab = function() {
|
|
|
|
if (document.getElementById(self.tab)) {
|
|
|
|
document.getElementById(self.tab).className = 'tab-out tab-view ' + self.tab;
|
|
|
|
var old = document.getElementById('menu-' + self.tab);
|
|
|
|
if (old) {
|
|
|
|
old.className = '';
|
|
|
|
}
|
2015-04-23 12:17:18 -07:00
|
|
|
}
|
2015-04-23 10:12:32 -07:00
|
|
|
|
2015-09-10 08:17:24 -07:00
|
|
|
if (document.getElementById(tab)) {
|
|
|
|
document.getElementById(tab).className = 'tab-in tab-view ' + tab;
|
|
|
|
var newe = document.getElementById('menu-' + tab);
|
|
|
|
if (newe) {
|
|
|
|
newe.className = 'active';
|
|
|
|
}
|
2015-04-23 14:05:31 -07:00
|
|
|
}
|
2015-09-10 08:17:24 -07:00
|
|
|
|
|
|
|
self.tab = tab;
|
|
|
|
$rootScope.$emit('Local/TabChanged', tab);
|
|
|
|
};
|
|
|
|
|
2016-05-24 11:58:59 -07:00
|
|
|
if (switchState && !go.is('walletHome')) {
|
2015-09-10 08:17:24 -07:00
|
|
|
go.path('walletHome', function() {
|
|
|
|
changeTab();
|
|
|
|
});
|
|
|
|
return;
|
2015-09-07 07:14:09 -07:00
|
|
|
}
|
2015-04-23 10:12:32 -07:00
|
|
|
|
2015-09-10 08:17:24 -07:00
|
|
|
changeTab();
|
2015-04-23 09:12:30 -07:00
|
|
|
};
|
|
|
|
|
2015-05-19 10:10:47 -07:00
|
|
|
|
|
|
|
|
2015-05-30 10:28:18 -07:00
|
|
|
var _walletStatusHash = function(walletStatus) {
|
2015-05-30 18:38:08 -07:00
|
|
|
var bal;
|
2015-05-30 10:28:18 -07:00
|
|
|
if (walletStatus) {
|
2015-05-30 18:38:08 -07:00
|
|
|
bal = walletStatus.balance.totalAmount;
|
2015-05-30 10:28:18 -07:00
|
|
|
} else {
|
2015-05-30 18:38:08 -07:00
|
|
|
bal = self.totalBalanceSat;
|
2015-05-30 10:28:18 -07:00
|
|
|
}
|
2015-05-30 18:38:08 -07:00
|
|
|
return bal;
|
2015-05-30 10:28:18 -07:00
|
|
|
};
|
2015-05-19 10:10:47 -07:00
|
|
|
|
2016-06-06 14:26:45 -07:00
|
|
|
// TODO move this to wallet service
|
2015-06-12 22:01:02 -07:00
|
|
|
self.updateAll = function(opts, initStatusHash, tries) {
|
2016-05-17 07:10:16 -07:00
|
|
|
$scope.$broadcast('scroll.refreshComplete');
|
2015-05-18 12:21:36 -07:00
|
|
|
tries = tries || 0;
|
2015-06-19 11:09:15 -07:00
|
|
|
opts = opts || {};
|
2016-04-13 08:46:25 -07:00
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
if (!fc) return;
|
2015-06-19 11:09:15 -07:00
|
|
|
|
2016-04-13 08:46:25 -07:00
|
|
|
var walletId = fc.credentials.walletId
|
2016-02-23 06:12:49 -08:00
|
|
|
|
2015-06-19 11:09:15 -07:00
|
|
|
if (opts.untilItChanges && lodash.isUndefined(initStatusHash)) {
|
2015-05-30 10:28:18 -07:00
|
|
|
initStatusHash = _walletStatusHash();
|
2015-05-30 18:38:08 -07:00
|
|
|
$log.debug('Updating status until it changes. initStatusHash:' + initStatusHash)
|
2015-05-18 12:21:36 -07:00
|
|
|
}
|
2016-06-11 09:52:44 -07:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
var get = function(cb) {
|
2015-06-19 11:09:15 -07:00
|
|
|
if (opts.walletStatus)
|
2015-06-12 22:01:02 -07:00
|
|
|
return cb(null, opts.walletStatus);
|
2015-04-13 10:58:07 -07:00
|
|
|
else {
|
|
|
|
self.updateError = false;
|
2016-01-15 08:41:18 -08:00
|
|
|
return fc.getStatus({
|
|
|
|
twoStep: true
|
|
|
|
}, function(err, ret) {
|
2015-04-15 10:03:38 -07:00
|
|
|
if (err) {
|
2015-08-12 07:52:04 -07:00
|
|
|
self.updateError = bwsError.msg(err, gettext('Could not update Wallet'));
|
2015-04-15 10:03:38 -07:00
|
|
|
} else {
|
2016-06-07 06:37:06 -07:00
|
|
|
self.isSingleAddress = !!ret.wallet.singleAddress;
|
2015-06-19 11:09:15 -07:00
|
|
|
if (!opts.quiet)
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('scanning', ret.wallet.scanStatus == 'running');
|
2015-04-15 10:03:38 -07:00
|
|
|
}
|
2015-04-13 10:58:07 -07:00
|
|
|
return cb(err, ret);
|
|
|
|
});
|
|
|
|
}
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
2016-02-23 06:12:49 -08:00
|
|
|
// If not untilItChanges...trigger history update now
|
|
|
|
if (opts.triggerTxUpdate && !opts.untilItChanges) {
|
|
|
|
$timeout(function() {
|
|
|
|
self.debounceUpdateHistory();
|
|
|
|
}, 1);
|
|
|
|
}
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
$timeout(function() {
|
2015-06-19 11:09:15 -07:00
|
|
|
|
|
|
|
if (!opts.quiet)
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('updatingStatus', true);
|
2015-06-19 11:09:15 -07:00
|
|
|
|
2015-09-08 04:47:36 -07:00
|
|
|
$log.debug('Updating Status:', fc.credentials.walletName, tries);
|
2015-03-06 07:00:10 -08:00
|
|
|
get(function(err, walletStatus) {
|
2015-06-29 17:46:34 -07:00
|
|
|
var currentStatusHash = _walletStatusHash(walletStatus);
|
|
|
|
$log.debug('Status update. hash:' + currentStatusHash + ' Try:' + tries);
|
2016-02-23 06:12:49 -08:00
|
|
|
if (!err && opts.untilItChanges && initStatusHash == currentStatusHash && tries < 7 && walletId == profileService.focusedClient.credentials.walletId) {
|
2015-05-18 12:21:36 -07:00
|
|
|
return $timeout(function() {
|
2015-05-30 18:38:08 -07:00
|
|
|
$log.debug('Retrying update... Try:' + tries)
|
2015-06-29 17:46:34 -07:00
|
|
|
return self.updateAll({
|
|
|
|
walletStatus: null,
|
2015-07-13 09:09:52 -07:00
|
|
|
untilItChanges: true,
|
|
|
|
triggerTxUpdate: opts.triggerTxUpdate,
|
2015-06-29 17:46:34 -07:00
|
|
|
}, initStatusHash, ++tries);
|
2015-05-29 08:39:17 -07:00
|
|
|
}, 1400 * tries);
|
2015-05-18 12:21:36 -07:00
|
|
|
}
|
2016-02-23 06:12:49 -08:00
|
|
|
|
|
|
|
if (walletId != profileService.focusedClient.credentials.walletId)
|
|
|
|
return;
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('updatingStatus', false);
|
2015-06-19 11:09:15 -07:00
|
|
|
|
2016-02-23 06:12:49 -08:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
if (err) {
|
|
|
|
self.handleError(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$log.debug('Wallet Status:', walletStatus);
|
|
|
|
self.setPendingTxps(walletStatus.pendingTxps);
|
|
|
|
|
|
|
|
// Status Shortcuts
|
2016-06-11 09:52:44 -07:00
|
|
|
self.lastUpdate = Date.now();
|
2015-03-06 07:00:10 -08:00
|
|
|
self.walletName = walletStatus.wallet.name;
|
|
|
|
self.walletSecret = walletStatus.wallet.secret;
|
|
|
|
self.walletStatus = walletStatus.wallet.status;
|
2015-04-15 10:03:38 -07:00
|
|
|
self.walletScanStatus = walletStatus.wallet.scanStatus;
|
2015-03-06 07:00:10 -08:00
|
|
|
self.copayers = walletStatus.wallet.copayers;
|
2015-05-19 10:10:47 -07:00
|
|
|
self.preferences = walletStatus.preferences;
|
2015-03-06 07:00:10 -08:00
|
|
|
self.setBalance(walletStatus.balance);
|
2015-06-27 09:48:25 -07:00
|
|
|
self.otherWallets = lodash.filter(profileService.getWallets(self.network), function(w) {
|
|
|
|
return w.id != self.walletId;
|
2015-09-11 09:11:41 -07:00
|
|
|
});
|
2015-07-13 12:25:34 -07:00
|
|
|
|
|
|
|
// Notify external addons or plugins
|
|
|
|
$rootScope.$emit('Local/BalanceUpdated', walletStatus.balance);
|
2015-04-21 13:49:17 -07:00
|
|
|
$rootScope.$apply();
|
2015-07-06 06:40:40 -07:00
|
|
|
|
2016-03-09 06:53:47 -08:00
|
|
|
|
2016-02-23 06:12:49 -08:00
|
|
|
if (opts.triggerTxUpdate && opts.untilItChanges) {
|
2015-07-06 06:40:40 -07:00
|
|
|
$timeout(function() {
|
2015-12-09 06:57:43 -08:00
|
|
|
self.debounceUpdateHistory();
|
2015-07-06 06:40:40 -07:00
|
|
|
}, 1);
|
2016-02-24 08:27:22 -08:00
|
|
|
} else {
|
|
|
|
self.loadingWallet = false;
|
2015-07-06 06:40:40 -07:00
|
|
|
}
|
2016-03-09 06:53:47 -08:00
|
|
|
|
|
|
|
if (opts.cb) return opts.cb();
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-12-23 13:05:22 -08:00
|
|
|
self.setSpendUnconfirmed = function(spendUnconfirmed) {
|
|
|
|
self.spendUnconfirmed = spendUnconfirmed || configService.getSync().wallet.spendUnconfirmed;
|
2016-02-23 08:19:37 -08:00
|
|
|
};
|
2015-07-24 08:11:07 -07:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.updateBalance = function() {
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
$timeout(function() {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('updatingBalance', true);
|
2015-03-06 07:00:10 -08:00
|
|
|
$log.debug('Updating Balance');
|
|
|
|
fc.getBalance(function(err, balance) {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('updatingBalance', false);
|
2015-03-06 07:00:10 -08:00
|
|
|
if (err) {
|
2015-08-12 09:04:39 -07:00
|
|
|
self.handleError(err);
|
2015-03-06 07:00:10 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
$log.debug('Wallet Balance:', balance);
|
|
|
|
self.setBalance(balance);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
self.updatePendingTxps = function() {
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
$timeout(function() {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('updatingPendingTxps', true);
|
2015-03-06 07:00:10 -08:00
|
|
|
$log.debug('Updating PendingTxps');
|
2015-04-18 03:08:08 -07:00
|
|
|
fc.getTxProposals({}, function(err, txps) {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('updatingPendingTxps', false);
|
2015-03-06 07:00:10 -08:00
|
|
|
if (err) {
|
2015-08-12 09:04:39 -07:00
|
|
|
self.handleError(err);
|
2015-03-06 07:00:10 -08:00
|
|
|
} else {
|
|
|
|
$log.debug('Wallet PendingTxps:', txps);
|
|
|
|
self.setPendingTxps(txps);
|
|
|
|
}
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
2016-05-30 09:26:48 -07:00
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
2016-01-16 15:04:01 -08:00
|
|
|
// This handles errors from BWS/index which normally
|
2015-11-26 08:25:38 -08:00
|
|
|
// trigger from async events (like updates).
|
|
|
|
// Debounce function avoids multiple popups
|
|
|
|
var _handleError = function(err) {
|
|
|
|
$log.warn('Client ERROR: ', err);
|
2016-01-22 13:16:50 -08:00
|
|
|
if (err instanceof errors.NOT_AUTHORIZED) {
|
2015-08-12 09:04:39 -07:00
|
|
|
self.notAuthorized = true;
|
|
|
|
go.walletHome();
|
2016-01-22 13:16:50 -08:00
|
|
|
} else if (err instanceof errors.NOT_FOUND) {
|
2015-08-12 09:04:39 -07:00
|
|
|
self.showErrorPopup(gettext('Could not access Wallet Service: Not found'));
|
2015-03-06 07:00:10 -08:00
|
|
|
} else {
|
2015-08-12 09:04:39 -07:00
|
|
|
var msg = ""
|
2015-04-27 10:18:22 -07:00
|
|
|
$scope.$emit('Local/ClientError', (err.error ? err.error : err));
|
2015-08-12 09:04:39 -07:00
|
|
|
var msg = bwsError.msg(err, gettext('Error at Wallet Service'));
|
|
|
|
self.showErrorPopup(msg);
|
2015-03-06 07:00:10 -08:00
|
|
|
}
|
|
|
|
};
|
2015-11-26 08:25:38 -08:00
|
|
|
|
|
|
|
self.handleError = lodash.debounce(_handleError, 1000);
|
|
|
|
|
2016-03-09 06:53:47 -08:00
|
|
|
self.openWallet = function(cb) {
|
2015-03-06 07:00:10 -08:00
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
$timeout(function() {
|
2015-04-23 11:32:11 -07:00
|
|
|
$rootScope.$apply();
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('openingWallet', true);
|
2015-04-14 12:06:04 -07:00
|
|
|
self.updateError = false;
|
2015-03-06 07:00:10 -08:00
|
|
|
fc.openWallet(function(err, walletStatus) {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('openingWallet', false);
|
2015-03-06 07:00:10 -08:00
|
|
|
if (err) {
|
2015-04-14 12:06:04 -07:00
|
|
|
self.updateError = true;
|
2015-03-06 07:00:10 -08:00
|
|
|
self.handleError(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$log.debug('Wallet Opened');
|
2016-03-09 06:53:47 -08:00
|
|
|
|
2015-06-29 17:46:34 -07:00
|
|
|
self.updateAll(lodash.isObject(walletStatus) ? {
|
2016-03-09 06:53:47 -08:00
|
|
|
walletStatus: walletStatus,
|
|
|
|
cb: cb,
|
|
|
|
} : {
|
|
|
|
cb: cb
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setPendingTxps = function(txps) {
|
|
|
|
self.pendingTxProposalsCountForUs = 0;
|
2015-09-25 09:25:37 -07:00
|
|
|
var now = Math.floor(Date.now() / 1000);
|
|
|
|
|
2015-12-16 11:22:40 -08:00
|
|
|
/* Uncomment to test multiple outputs */
|
|
|
|
/*
|
|
|
|
var txp = {
|
|
|
|
message: 'test multi-output',
|
|
|
|
fee: 1000,
|
|
|
|
createdOn: new Date() / 1000,
|
|
|
|
outputs: []
|
|
|
|
};
|
|
|
|
function addOutput(n) {
|
|
|
|
txp.outputs.push({
|
|
|
|
amount: 600,
|
|
|
|
toAddress: '2N8bhEwbKtMvR2jqMRcTCQqzHP6zXGToXcK',
|
|
|
|
message: 'output #' + (Number(n) + 1)
|
|
|
|
});
|
|
|
|
};
|
|
|
|
lodash.times(150, addOutput);
|
|
|
|
txps.push(txp);
|
|
|
|
*/
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
lodash.each(txps, function(tx) {
|
2015-09-18 09:59:18 -07:00
|
|
|
|
2015-09-09 12:17:08 -07:00
|
|
|
tx = txFormatService.processTx(tx);
|
2015-03-06 07:00:10 -08:00
|
|
|
|
2015-09-25 09:25:37 -07:00
|
|
|
// no future transactions...
|
|
|
|
if (tx.createdOn > now)
|
|
|
|
tx.createdOn = now;
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
var action = lodash.find(tx.actions, {
|
|
|
|
copayerId: self.copayerId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!action && tx.status == 'pending') {
|
|
|
|
tx.pendingForUs = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action && action.type == 'accept') {
|
|
|
|
tx.statusForUs = 'accepted';
|
|
|
|
} else if (action && action.type == 'reject') {
|
|
|
|
tx.statusForUs = 'rejected';
|
|
|
|
} else {
|
|
|
|
tx.statusForUs = 'pending';
|
|
|
|
}
|
|
|
|
|
2015-06-18 07:17:35 -07:00
|
|
|
if (!tx.deleteLockTime)
|
|
|
|
tx.canBeRemoved = true;
|
2015-03-06 07:00:10 -08:00
|
|
|
|
|
|
|
if (tx.creatorId != self.copayerId) {
|
|
|
|
self.pendingTxProposalsCountForUs = self.pendingTxProposalsCountForUs + 1;
|
|
|
|
}
|
2015-08-03 05:49:44 -07:00
|
|
|
addonManager.formatPendingTxp(tx);
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
self.txps = txps;
|
|
|
|
};
|
|
|
|
|
2015-09-18 09:59:18 -07:00
|
|
|
var SAFE_CONFIRMATIONS = 6;
|
|
|
|
|
2015-11-06 08:06:08 -08:00
|
|
|
self.processNewTxs = function(txs) {
|
2015-07-17 10:30:55 -07:00
|
|
|
var config = configService.getSync().wallet.settings;
|
2015-07-13 09:31:05 -07:00
|
|
|
var now = Math.floor(Date.now() / 1000);
|
2015-11-06 08:06:08 -08:00
|
|
|
var txHistoryUnique = {};
|
|
|
|
var ret = [];
|
2015-09-18 09:59:18 -07:00
|
|
|
self.hasUnsafeConfirmed = false;
|
2015-11-06 08:06:08 -08:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
lodash.each(txs, function(tx) {
|
2015-09-09 12:17:08 -07:00
|
|
|
tx = txFormatService.processTx(tx);
|
2015-07-13 09:31:05 -07:00
|
|
|
|
|
|
|
// no future transactions...
|
|
|
|
if (tx.time > now)
|
|
|
|
tx.time = now;
|
|
|
|
|
2015-09-18 09:59:18 -07:00
|
|
|
if (tx.confirmations >= SAFE_CONFIRMATIONS) {
|
|
|
|
tx.safeConfirmed = SAFE_CONFIRMATIONS + '+';
|
|
|
|
} else {
|
|
|
|
tx.safeConfirmed = false;
|
|
|
|
self.hasUnsafeConfirmed = true;
|
|
|
|
}
|
|
|
|
|
2016-06-03 11:21:30 -07:00
|
|
|
if (tx.note) {
|
|
|
|
delete tx.note.encryptedEditedByName;
|
|
|
|
delete tx.note.encryptedBody;
|
|
|
|
}
|
|
|
|
|
2015-11-06 08:06:08 -08:00
|
|
|
if (!txHistoryUnique[tx.txid]) {
|
|
|
|
ret.push(tx);
|
|
|
|
txHistoryUnique[tx.txid] = true;
|
2015-10-22 06:14:57 -07:00
|
|
|
} else {
|
|
|
|
$log.debug('Ignoring duplicate TX in history: ' + tx.txid)
|
2015-03-06 07:00:10 -08:00
|
|
|
}
|
|
|
|
});
|
2015-11-06 08:06:08 -08:00
|
|
|
|
|
|
|
return ret;
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
2015-05-14 06:39:22 -07:00
|
|
|
self.updateAlias = function() {
|
|
|
|
var config = configService.getSync();
|
|
|
|
config.aliasFor = config.aliasFor || {};
|
|
|
|
self.alias = config.aliasFor[self.walletId];
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
fc.alias = self.alias;
|
|
|
|
};
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.updateColor = function() {
|
|
|
|
var config = configService.getSync();
|
|
|
|
config.colorFor = config.colorFor || {};
|
2015-05-29 11:25:41 -07:00
|
|
|
self.backgroundColor = config.colorFor[self.walletId] || '#4A90E2';
|
2015-03-06 07:00:10 -08:00
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
fc.backgroundColor = self.backgroundColor;
|
2015-12-01 12:16:39 -08:00
|
|
|
if (isCordova && StatusBar.isVisible) {
|
|
|
|
StatusBar.backgroundColorByHexString(fc.backgroundColor);
|
|
|
|
}
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
self.setBalance = function(balance) {
|
|
|
|
if (!balance) return;
|
|
|
|
var config = configService.getSync().wallet.settings;
|
|
|
|
var COIN = 1e8;
|
|
|
|
|
2015-08-11 13:11:40 -07:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
// Address with Balance
|
|
|
|
self.balanceByAddress = balance.byAddress;
|
|
|
|
|
2015-12-24 08:43:12 -08:00
|
|
|
// Spend unconfirmed funds
|
2015-08-11 13:45:57 -07:00
|
|
|
if (self.spendUnconfirmed) {
|
|
|
|
self.totalBalanceSat = balance.totalAmount;
|
|
|
|
self.lockedBalanceSat = balance.lockedAmount;
|
|
|
|
self.availableBalanceSat = balance.availableAmount;
|
2015-12-24 08:43:12 -08:00
|
|
|
self.totalBytesToSendMax = balance.totalBytesToSendMax;
|
2015-08-11 13:45:57 -07:00
|
|
|
self.pendingAmount = null;
|
|
|
|
} else {
|
|
|
|
self.totalBalanceSat = balance.totalConfirmedAmount;
|
|
|
|
self.lockedBalanceSat = balance.lockedConfirmedAmount;
|
|
|
|
self.availableBalanceSat = balance.availableConfirmedAmount;
|
2015-12-24 08:43:12 -08:00
|
|
|
self.totalBytesToSendMax = balance.totalBytesToSendConfirmedMax;
|
2015-08-11 13:45:57 -07:00
|
|
|
self.pendingAmount = balance.totalAmount - balance.totalConfirmedAmount;
|
|
|
|
}
|
2015-03-06 07:00:10 -08:00
|
|
|
|
|
|
|
// Selected unit
|
|
|
|
self.unitToSatoshi = config.unitToSatoshi;
|
|
|
|
self.satToUnit = 1 / self.unitToSatoshi;
|
|
|
|
self.unitName = config.unitName;
|
|
|
|
|
|
|
|
//STR
|
|
|
|
self.totalBalanceStr = profileService.formatAmount(self.totalBalanceSat) + ' ' + self.unitName;
|
|
|
|
self.lockedBalanceStr = profileService.formatAmount(self.lockedBalanceSat) + ' ' + self.unitName;
|
|
|
|
self.availableBalanceStr = profileService.formatAmount(self.availableBalanceSat) + ' ' + self.unitName;
|
|
|
|
|
2015-08-11 13:45:57 -07:00
|
|
|
if (self.pendingAmount) {
|
|
|
|
self.pendingAmountStr = profileService.formatAmount(self.pendingAmount) + ' ' + self.unitName;
|
|
|
|
} else {
|
|
|
|
self.pendingAmountStr = null;
|
|
|
|
}
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.alternativeName = config.alternativeName;
|
|
|
|
self.alternativeIsoCode = config.alternativeIsoCode;
|
|
|
|
|
|
|
|
// Check address
|
2015-06-29 17:46:34 -07:00
|
|
|
addressService.isUsed(self.walletId, balance.byAddress, function(err, used) {
|
|
|
|
if (used) {
|
2015-06-27 09:22:56 -07:00
|
|
|
$log.debug('Address used. Creating new');
|
2016-02-18 12:16:07 -08:00
|
|
|
$rootScope.$emit('Local/AddressIsUsed');
|
2015-06-27 09:22:56 -07:00
|
|
|
}
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
|
|
|
|
rateService.whenAvailable(function() {
|
|
|
|
|
2015-08-11 13:45:57 -07:00
|
|
|
var totalBalanceAlternative = rateService.toFiat(self.totalBalanceSat, self.alternativeIsoCode);
|
|
|
|
var lockedBalanceAlternative = rateService.toFiat(self.lockedBalanceSat, self.alternativeIsoCode);
|
2015-03-06 07:00:10 -08:00
|
|
|
var alternativeConversionRate = rateService.toFiat(100000000, self.alternativeIsoCode);
|
|
|
|
|
|
|
|
self.totalBalanceAlternative = $filter('noFractionNumber')(totalBalanceAlternative, 2);
|
|
|
|
self.lockedBalanceAlternative = $filter('noFractionNumber')(lockedBalanceAlternative, 2);
|
|
|
|
self.alternativeConversionRate = $filter('noFractionNumber')(alternativeConversionRate, 2);
|
|
|
|
|
|
|
|
self.alternativeBalanceAvailable = true;
|
|
|
|
|
|
|
|
self.isRateAvailable = true;
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!rateService.isAvailable()) {
|
|
|
|
$rootScope.$apply();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-02-23 08:19:37 -08:00
|
|
|
self.removeAndMarkSoftConfirmedTx = function(txs) {
|
2016-02-18 12:16:07 -08:00
|
|
|
return lodash.filter(txs, function(tx) {
|
2015-10-23 09:26:59 -07:00
|
|
|
if (tx.confirmations >= SOFT_CONFIRMATION_LIMIT)
|
2015-10-22 07:43:30 -07:00
|
|
|
return tx;
|
2016-02-23 08:19:37 -08:00
|
|
|
tx.recent = true;
|
2015-10-22 07:43:30 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
self.getSavedTxs = function(walletId, cb) {
|
2015-10-09 11:23:04 -07:00
|
|
|
|
2015-11-10 15:05:05 -08:00
|
|
|
storageService.getTxHistory(walletId, function(err, txs) {
|
2015-10-08 10:29:35 -07:00
|
|
|
if (err) return cb(err);
|
2015-07-17 10:43:40 -07:00
|
|
|
|
2015-10-23 09:26:59 -07:00
|
|
|
var localTxs = [];
|
2015-10-30 13:03:08 -07:00
|
|
|
|
|
|
|
if (!txs) {
|
|
|
|
return cb(null, localTxs);
|
|
|
|
}
|
|
|
|
|
2015-10-08 10:29:35 -07:00
|
|
|
try {
|
2015-10-22 07:43:30 -07:00
|
|
|
localTxs = JSON.parse(txs);
|
2015-10-08 10:29:35 -07:00
|
|
|
} catch (ex) {
|
2015-10-23 09:26:59 -07:00
|
|
|
$log.warn(ex);
|
2015-10-08 10:29:35 -07:00
|
|
|
}
|
2016-02-18 12:16:07 -08:00
|
|
|
return cb(null, lodash.compact(localTxs));
|
2015-10-23 09:26:59 -07:00
|
|
|
});
|
|
|
|
}
|
2015-10-22 07:43:30 -07:00
|
|
|
|
2015-11-10 15:05:05 -08:00
|
|
|
self.updateLocalTxHistory = function(client, cb) {
|
2016-02-18 12:16:07 -08:00
|
|
|
var FIRST_LIMIT = 5;
|
|
|
|
var LIMIT = 50;
|
|
|
|
var requestLimit = FIRST_LIMIT;
|
2015-11-10 15:05:05 -08:00
|
|
|
var walletId = client.credentials.walletId;
|
2015-11-18 05:24:15 -08:00
|
|
|
var config = configService.getSync().wallet.settings;
|
|
|
|
|
|
|
|
var fixTxsUnit = function(txs) {
|
2016-02-29 05:25:41 -08:00
|
|
|
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
2015-11-18 05:24:15 -08:00
|
|
|
|
|
|
|
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, config.unitName) + name;
|
|
|
|
tx.feeStr = profileService.formatAmount(tx.fees, config.unitName) + name;
|
|
|
|
});
|
|
|
|
};
|
2015-11-06 08:06:08 -08:00
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
self.getSavedTxs(walletId, function(err, txsFromLocal) {
|
2015-10-23 09:26:59 -07:00
|
|
|
if (err) return cb(err);
|
2015-11-06 08:06:08 -08:00
|
|
|
|
2015-11-18 05:24:15 -08:00
|
|
|
fixTxsUnit(txsFromLocal);
|
|
|
|
|
2016-02-23 08:19:37 -08:00
|
|
|
var confirmedTxs = self.removeAndMarkSoftConfirmedTx(txsFromLocal);
|
2016-02-18 12:16:07 -08:00
|
|
|
var endingTxid = confirmedTxs[0] ? confirmedTxs[0].txid : null;
|
2016-06-04 12:14:24 -07:00
|
|
|
var endingTs = confirmedTxs[0] ? confirmedTxs[0].time : null;
|
2016-02-18 12:16:07 -08:00
|
|
|
|
2016-02-23 06:12:49 -08:00
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
// First update
|
|
|
|
if (walletId == profileService.focusedClient.credentials.walletId) {
|
|
|
|
self.completeHistory = txsFromLocal;
|
|
|
|
self.setCompactTxHistory();
|
|
|
|
}
|
|
|
|
|
2016-02-23 08:19:37 -08:00
|
|
|
if (historyUpdateInProgress[walletId])
|
2016-02-23 06:12:49 -08:00
|
|
|
return;
|
2016-02-23 08:19:37 -08:00
|
|
|
|
2016-02-23 06:12:49 -08:00
|
|
|
historyUpdateInProgress[walletId] = true;
|
2016-02-18 12:16:07 -08:00
|
|
|
|
2015-11-06 08:06:08 -08:00
|
|
|
function getNewTxs(newTxs, skip, i_cb) {
|
2015-11-10 15:05:05 -08:00
|
|
|
self.getTxsFromServer(client, skip, endingTxid, requestLimit, function(err, res, shouldContinue) {
|
2015-11-06 08:06:08 -08:00
|
|
|
if (err) return i_cb(err);
|
|
|
|
|
2015-11-10 15:05:05 -08:00
|
|
|
newTxs = newTxs.concat(lodash.compact(res));
|
2015-11-06 08:06:08 -08:00
|
|
|
skip = skip + requestLimit;
|
|
|
|
|
|
|
|
$log.debug('Syncing TXs. Got:' + newTxs.length + ' Skip:' + skip, ' EndingTxid:', endingTxid, ' Continue:', shouldContinue);
|
|
|
|
|
|
|
|
if (!shouldContinue) {
|
|
|
|
newTxs = self.processNewTxs(newTxs);
|
2016-02-23 08:19:37 -08:00
|
|
|
$log.debug('Finished Sync: New / soft confirmed Txs: ' + newTxs.length);
|
2015-11-06 08:06:08 -08:00
|
|
|
return i_cb(null, newTxs);
|
2015-10-23 09:26:59 -07:00
|
|
|
}
|
2015-11-06 08:06:08 -08:00
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
requestLimit = LIMIT;
|
2015-11-06 08:06:08 -08:00
|
|
|
getNewTxs(newTxs, skip, i_cb);
|
2016-02-18 12:16:07 -08:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
});
|
|
|
|
}
|
2015-10-09 11:23:04 -07:00
|
|
|
});
|
|
|
|
};
|
2015-11-06 08:06:08 -08:00
|
|
|
|
|
|
|
getNewTxs([], 0, function(err, txs) {
|
|
|
|
if (err) return cb(err);
|
2015-12-10 07:44:40 -08:00
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
var newHistory = lodash.uniq(lodash.compact(txs.concat(confirmedTxs)), function(x) {
|
|
|
|
return x.txid;
|
|
|
|
});
|
2016-02-23 08:19:37 -08:00
|
|
|
|
|
|
|
|
2016-06-04 12:14:24 -07:00
|
|
|
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();
|
|
|
|
});
|
2015-11-10 15:05:05 -08:00
|
|
|
}
|
2015-11-06 08:06:08 -08:00
|
|
|
|
2016-06-04 12:14:24 -07:00
|
|
|
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.');
|
2016-02-18 12:16:07 -08:00
|
|
|
|
2016-06-04 12:14:24 -07:00
|
|
|
return cb();
|
|
|
|
});
|
2015-11-06 08:06:08 -08:00
|
|
|
});
|
|
|
|
});
|
2015-10-08 10:29:35 -07:00
|
|
|
});
|
|
|
|
}
|
2016-02-09 10:10:25 -08:00
|
|
|
|
2016-02-22 12:33:41 -08:00
|
|
|
self.showMore = function() {
|
2015-11-06 08:06:08 -08:00
|
|
|
$timeout(function() {
|
2016-02-23 06:29:11 -08:00
|
|
|
if (self.isSearching) {
|
2016-02-25 11:03:03 -08:00
|
|
|
self.txHistorySearchResults = self.result.slice(0, self.nextTxHistory);
|
|
|
|
$log.debug('Total txs: ', self.txHistorySearchResults.length + '/' + self.result.length);
|
|
|
|
if (self.txHistorySearchResults.length >= self.result.length)
|
|
|
|
self.historyShowMore = false;
|
|
|
|
} else {
|
|
|
|
self.txHistory = self.completeHistory.slice(0, self.nextTxHistory);
|
2016-05-24 10:10:53 -07:00
|
|
|
$log.debug('Total txs: ', self.txHistory.length + '/' + self.completeHistory.length);
|
|
|
|
if (self.txHistory.length >= self.completeHistory.length)
|
2016-02-25 11:03:03 -08:00
|
|
|
self.historyShowMore = false;
|
|
|
|
}
|
|
|
|
self.nextTxHistory += self.historyShowMoreLimit;
|
2016-05-17 07:10:16 -07:00
|
|
|
$scope.$broadcast('scroll.infiniteScrollComplete');
|
2015-11-10 15:14:06 -08:00
|
|
|
}, 100);
|
2015-11-06 08:06:08 -08:00
|
|
|
};
|
2015-10-08 10:29:35 -07:00
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
self.startSearch = function() {
|
2016-02-19 07:26:12 -08:00
|
|
|
self.isSearching = true;
|
2016-02-23 10:50:46 -08:00
|
|
|
self.txHistorySearchResults = [];
|
2016-02-23 06:29:11 -08:00
|
|
|
self.result = [];
|
2016-02-22 06:29:27 -08:00
|
|
|
self.historyShowMore = false;
|
2016-02-23 06:29:11 -08:00
|
|
|
self.nextTxHistory = self.historyShowMoreLimit;
|
2016-02-19 07:26:12 -08:00
|
|
|
}
|
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
self.cancelSearch = function() {
|
2016-02-19 08:19:19 -08:00
|
|
|
self.isSearching = false;
|
2016-02-23 06:29:11 -08:00
|
|
|
self.result = [];
|
|
|
|
self.setCompactTxHistory();
|
2016-02-19 07:26:12 -08:00
|
|
|
}
|
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
self.updateSearchInput = function(search) {
|
2016-02-19 07:26:12 -08:00
|
|
|
self.search = search;
|
2016-02-19 08:19:19 -08:00
|
|
|
if (isCordova)
|
|
|
|
window.plugins.toast.hide();
|
2016-02-19 07:26:12 -08:00
|
|
|
self.throttleSearch();
|
2016-05-24 10:10:53 -07:00
|
|
|
$ionicScrollDelegate.resize();
|
2016-02-19 07:26:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
self.throttleSearch = lodash.throttle(function() {
|
2016-02-15 07:50:21 -08:00
|
|
|
|
2016-02-18 12:55:57 -08:00
|
|
|
function filter(search) {
|
2016-02-22 06:29:27 -08:00
|
|
|
self.result = [];
|
2016-02-23 11:43:17 -08:00
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
function computeSearchableString(tx) {
|
2016-02-23 11:43:17 -08:00
|
|
|
var addrbook = '';
|
2016-02-25 11:03:03 -08:00
|
|
|
if (tx.addressTo && self.addressbook && self.addressbook[tx.addressTo]) addrbook = self.addressbook[tx.addressTo] || '';
|
2016-02-23 11:43:17 -08:00
|
|
|
var searchableDate = computeSearchableDate(new Date(tx.time * 1000));
|
|
|
|
var message = tx.message ? tx.message : '';
|
2016-06-04 13:47:58 -07:00
|
|
|
var comment = tx.note ? tx.note.body : '';
|
2016-02-23 11:43:17 -08:00
|
|
|
var addressTo = tx.addressTo ? tx.addressTo : '';
|
2016-06-04 13:47:58 -07:00
|
|
|
return ((tx.amountStr + message + addressTo + addrbook + searchableDate + comment).toString()).toLowerCase();
|
2016-02-23 11:43:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
function computeSearchableDate(date) {
|
2016-02-18 12:55:57 -08:00
|
|
|
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('/');
|
|
|
|
};
|
2016-02-10 11:53:34 -08:00
|
|
|
|
2016-02-23 07:12:36 -08:00
|
|
|
if (lodash.isEmpty(search)) {
|
|
|
|
self.historyShowMore = false;
|
|
|
|
return [];
|
|
|
|
}
|
2016-02-22 06:29:27 -08:00
|
|
|
self.result = lodash.filter(self.completeHistory, function(tx) {
|
2016-02-23 11:43:17 -08:00
|
|
|
if (!tx.searcheableString) tx.searcheableString = computeSearchableString(tx);
|
2016-02-25 11:03:03 -08:00
|
|
|
return lodash.includes(tx.searcheableString, search.toLowerCase());
|
2016-02-18 12:55:57 -08:00
|
|
|
});
|
2016-02-19 08:19:19 -08:00
|
|
|
|
2016-02-22 06:29:27 -08:00
|
|
|
if (self.result.length > self.historyShowLimit) self.historyShowMore = true;
|
|
|
|
else self.historyShowMore = false;
|
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
return self.result;
|
2016-02-18 12:55:57 -08:00
|
|
|
};
|
|
|
|
|
2016-02-23 10:50:46 -08:00
|
|
|
self.txHistorySearchResults = filter(self.search).slice(0, self.historyShowLimit);
|
2016-02-19 08:19:19 -08:00
|
|
|
if (isCordova)
|
2016-02-23 07:23:58 -08:00
|
|
|
window.plugins.toast.showShortBottom(gettextCatalog.getString('Matches: ' + self.result.length));
|
2016-02-19 08:19:19 -08:00
|
|
|
|
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
2016-02-19 07:26:12 -08:00
|
|
|
|
2016-02-25 11:03:03 -08:00
|
|
|
}, 1000);
|
2016-02-05 08:00:40 -08:00
|
|
|
|
2015-11-10 15:05:05 -08:00
|
|
|
self.getTxsFromServer = function(client, skip, endingTxid, limit, cb) {
|
2015-11-06 08:06:08 -08:00
|
|
|
var res = [];
|
2015-10-09 11:23:04 -07:00
|
|
|
|
2015-11-10 15:05:05 -08:00
|
|
|
client.getTxHistory({
|
2015-11-06 08:06:08 -08:00
|
|
|
skip: skip,
|
|
|
|
limit: limit
|
|
|
|
}, function(err, txsFromServer) {
|
2015-10-09 11:23:04 -07:00
|
|
|
if (err) return cb(err);
|
|
|
|
|
2015-11-06 08:06:08 -08:00
|
|
|
if (!txsFromServer.length)
|
|
|
|
return cb();
|
2015-10-09 11:23:04 -07:00
|
|
|
|
2015-11-06 08:06:08 -08:00
|
|
|
var res = lodash.takeWhile(txsFromServer, function(tx) {
|
|
|
|
return tx.txid != endingTxid;
|
2015-10-09 11:23:04 -07:00
|
|
|
});
|
2015-11-06 08:06:08 -08:00
|
|
|
|
|
|
|
return cb(null, res, res.length == limit);
|
2015-10-09 11:23:04 -07:00
|
|
|
});
|
2015-11-06 08:06:08 -08:00
|
|
|
};
|
2015-10-09 11:23:04 -07:00
|
|
|
|
2015-10-22 08:31:54 -07:00
|
|
|
self.updateHistory = function() {
|
2015-11-04 07:50:25 -08:00
|
|
|
var fc = profileService.focusedClient;
|
2015-11-13 11:00:28 -08:00
|
|
|
if (!fc) return;
|
2015-11-10 15:05:05 -08:00
|
|
|
var walletId = fc.credentials.walletId;
|
|
|
|
|
2016-02-23 06:12:49 -08:00
|
|
|
if (!fc.isComplete()) {
|
2016-02-18 12:16:07 -08:00
|
|
|
return;
|
|
|
|
}
|
2015-11-04 07:50:25 -08:00
|
|
|
|
2015-10-09 11:23:04 -07:00
|
|
|
$log.debug('Updating Transaction History');
|
|
|
|
self.txHistoryError = false;
|
2016-02-23 06:12:49 -08:00
|
|
|
self.updatingTxHistory = true;
|
2015-10-09 11:23:04 -07:00
|
|
|
|
|
|
|
$timeout(function() {
|
2015-11-10 15:05:05 -08:00
|
|
|
self.updateLocalTxHistory(fc, function(err) {
|
2016-02-18 12:16:07 -08:00
|
|
|
historyUpdateInProgress[walletId] = self.updatingTxHistory = false;
|
2015-12-03 12:44:02 -08:00
|
|
|
self.loadingWallet = false;
|
|
|
|
self.txProgress = 0;
|
2015-11-10 15:05:05 -08:00
|
|
|
if (err)
|
2015-11-06 10:32:10 -08:00
|
|
|
self.txHistoryError = true;
|
|
|
|
|
2015-12-10 09:52:42 -08:00
|
|
|
$timeout(function() {
|
|
|
|
self.newTx = false
|
|
|
|
}, 1000);
|
|
|
|
|
2015-10-09 11:23:04 -07:00
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-02-09 12:09:23 -08:00
|
|
|
self.setCompactTxHistory = function() {
|
2016-02-23 07:34:16 -08:00
|
|
|
self.isSearching = false;
|
2016-02-22 12:33:41 -08:00
|
|
|
self.nextTxHistory = self.historyShowMoreLimit;
|
2016-04-11 07:53:23 -07:00
|
|
|
self.txHistory = self.completeHistory ? self.completeHistory.slice(0, self.historyShowLimit) : null;
|
|
|
|
self.historyShowMore = self.completeHistory ? self.completeHistory.length > self.historyShowLimit : null;
|
2016-02-09 12:09:23 -08:00
|
|
|
};
|
|
|
|
|
2015-12-09 06:57:43 -08:00
|
|
|
self.debounceUpdateHistory = lodash.debounce(function() {
|
2015-10-22 08:31:54 -07:00
|
|
|
self.updateHistory();
|
|
|
|
}, 1000);
|
|
|
|
|
|
|
|
self.throttledUpdateHistory = lodash.throttle(function() {
|
|
|
|
self.updateHistory();
|
2016-02-23 06:12:49 -08:00
|
|
|
}, 5000);
|
2015-10-09 11:23:04 -07:00
|
|
|
|
2015-09-04 20:11:14 -07:00
|
|
|
self.showErrorPopup = function(msg, cb) {
|
2015-08-12 09:04:39 -07:00
|
|
|
$log.warn('Showing err popup:' + msg);
|
2016-06-04 11:19:42 -07:00
|
|
|
|
|
|
|
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();
|
2015-08-12 09:04:39 -07:00
|
|
|
});
|
2015-04-24 12:39:12 -07:00
|
|
|
};
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.recreate = function(cb) {
|
|
|
|
var fc = profileService.focusedClient;
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('recreating', true);
|
2015-03-06 07:00:10 -08:00
|
|
|
fc.recreateWallet(function(err) {
|
|
|
|
self.notAuthorized = false;
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('recreating', false);
|
2015-03-06 07:00:10 -08:00
|
|
|
|
2015-04-14 08:51:49 -07:00
|
|
|
if (err) {
|
2015-04-27 10:14:51 -07:00
|
|
|
self.handleError(err);
|
2015-04-14 08:51:49 -07:00
|
|
|
$rootScope.$apply();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-06 15:09:57 -07:00
|
|
|
profileService.bindWalletClient(fc, {
|
2016-06-06 08:21:15 -07:00
|
|
|
force: true
|
|
|
|
});
|
2015-11-14 12:29:45 -08:00
|
|
|
self.startScan(self.walletId);
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-05-18 11:15:14 -07:00
|
|
|
self.toggleLeftMenu = function() {
|
2016-02-23 06:12:49 -08:00
|
|
|
profileService.isDisclaimerAccepted(function(val) {
|
2016-05-18 11:15:14 -07:00
|
|
|
if (val) go.toggleLeftMenu();
|
2016-02-23 06:12:49 -08:00
|
|
|
else
|
2016-02-22 14:32:24 -08:00
|
|
|
$log.debug('Disclaimer not accepted, cannot open menu');
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
2015-04-15 10:03:38 -07:00
|
|
|
self.retryScan = function() {
|
|
|
|
var self = this;
|
|
|
|
self.startScan(self.walletId);
|
|
|
|
}
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
self.startScan = function(walletId) {
|
2015-09-21 06:18:43 -07:00
|
|
|
$log.debug('Scanning wallet ' + walletId);
|
2015-03-06 07:00:10 -08:00
|
|
|
var c = profileService.walletClients[walletId];
|
2015-08-14 10:13:53 -07:00
|
|
|
if (!c.isComplete()) return;
|
2015-03-06 07:00:10 -08:00
|
|
|
|
|
|
|
if (self.walletId == walletId)
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('scanning', true);
|
2015-03-06 07:00:10 -08:00
|
|
|
|
|
|
|
c.startScan({
|
|
|
|
includeCopayerBranches: true,
|
|
|
|
}, function(err) {
|
2015-06-10 07:12:41 -07:00
|
|
|
if (err && self.walletId == walletId) {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('scanning', false);
|
2015-04-27 10:14:51 -07:00
|
|
|
self.handleError(err);
|
2015-04-14 08:51:49 -07:00
|
|
|
$rootScope.$apply();
|
2015-03-06 07:00:10 -08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-04-22 14:41:30 -07:00
|
|
|
|
2015-09-05 10:30:02 -07:00
|
|
|
self.initGlidera = function(accessToken) {
|
2015-09-11 09:11:41 -07:00
|
|
|
self.glideraEnabled = configService.getSync().glidera.enabled;
|
2015-11-05 13:57:59 -08:00
|
|
|
self.glideraTestnet = configService.getSync().glidera.testnet;
|
|
|
|
var network = self.glideraTestnet ? 'testnet' : 'livenet';
|
2015-09-11 09:11:41 -07:00
|
|
|
|
|
|
|
self.glideraToken = null;
|
|
|
|
self.glideraError = null;
|
|
|
|
self.glideraPermissions = null;
|
|
|
|
self.glideraEmail = null;
|
|
|
|
self.glideraPersonalInfo = null;
|
|
|
|
self.glideraTxs = null;
|
2015-09-08 18:39:33 -07:00
|
|
|
self.glideraStatus = null;
|
|
|
|
|
2015-10-05 11:06:53 -07:00
|
|
|
if (!self.glideraEnabled) return;
|
2015-09-11 09:11:41 -07:00
|
|
|
|
|
|
|
glideraService.setCredentials(network);
|
2015-09-05 10:30:02 -07:00
|
|
|
|
|
|
|
var getToken = function(cb) {
|
|
|
|
if (accessToken) {
|
|
|
|
cb(null, accessToken);
|
|
|
|
} else {
|
2015-09-11 09:11:41 -07:00
|
|
|
storageService.getGlideraToken(network, cb);
|
2015-09-05 10:30:02 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
getToken(function(err, accessToken) {
|
|
|
|
if (err || !accessToken) return;
|
2015-09-02 12:02:40 -07:00
|
|
|
else {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('connectingGlidera', true);
|
2015-09-07 07:14:09 -07:00
|
|
|
glideraService.getAccessTokenPermissions(accessToken, function(err, p) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('connectingGlidera', false);
|
2015-09-05 10:30:02 -07:00
|
|
|
if (err) {
|
|
|
|
self.glideraError = err;
|
2015-09-18 09:59:18 -07:00
|
|
|
} else {
|
2015-09-07 07:14:09 -07:00
|
|
|
self.glideraToken = accessToken;
|
2015-09-05 10:30:02 -07:00
|
|
|
self.glideraPermissions = p;
|
2015-09-18 09:59:18 -07:00
|
|
|
self.updateGlidera({
|
|
|
|
fullUpdate: true
|
|
|
|
});
|
2015-09-05 10:30:02 -07:00
|
|
|
}
|
2015-09-02 12:02:40 -07:00
|
|
|
});
|
|
|
|
}
|
2015-08-28 14:23:24 -07:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-09-09 06:39:35 -07:00
|
|
|
self.updateGlidera = function(opts) {
|
|
|
|
if (!self.glideraToken || !self.glideraPermissions) return;
|
|
|
|
var accessToken = self.glideraToken;
|
|
|
|
var permissions = self.glideraPermissions;
|
|
|
|
|
|
|
|
opts = opts || {};
|
2015-09-08 08:04:27 -07:00
|
|
|
|
|
|
|
glideraService.getStatus(accessToken, function(err, data) {
|
|
|
|
self.glideraStatus = data;
|
|
|
|
});
|
2015-09-08 13:36:08 -07:00
|
|
|
|
|
|
|
glideraService.getLimits(accessToken, function(err, limits) {
|
|
|
|
self.glideraLimits = limits;
|
|
|
|
});
|
2015-09-09 06:39:35 -07:00
|
|
|
|
|
|
|
if (permissions.transaction_history) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('Fetching Glidera Transactions', true);
|
2015-09-09 06:39:35 -07:00
|
|
|
glideraService.getTransactions(accessToken, function(err, data) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('Fetching Glidera Transactions', false);
|
2015-09-09 06:39:35 -07:00
|
|
|
self.glideraTxs = data;
|
|
|
|
});
|
|
|
|
}
|
2015-09-18 09:59:18 -07:00
|
|
|
|
2015-09-09 06:39:35 -07:00
|
|
|
if (permissions.view_email_address && opts.fullUpdate) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('connectingGlidera', true);
|
2015-09-05 10:30:02 -07:00
|
|
|
glideraService.getEmail(accessToken, function(err, data) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('connectingGlidera', false);
|
2015-09-05 10:30:02 -07:00
|
|
|
self.glideraEmail = data.email;
|
|
|
|
});
|
|
|
|
}
|
2015-09-09 06:39:35 -07:00
|
|
|
if (permissions.personal_info && opts.fullUpdate) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('connectingGlidera', true);
|
2015-09-05 10:30:02 -07:00
|
|
|
glideraService.getPersonalInfo(accessToken, function(err, data) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('connectingGlidera', false);
|
2015-09-05 10:30:02 -07:00
|
|
|
self.glideraPersonalInfo = data;
|
|
|
|
});
|
|
|
|
}
|
2015-09-09 06:39:35 -07:00
|
|
|
|
2015-09-05 10:30:02 -07:00
|
|
|
};
|
|
|
|
|
2016-04-13 10:08:03 -07:00
|
|
|
self.initCoinbase = function(accessToken) {
|
|
|
|
self.coinbaseEnabled = configService.getSync().coinbase.enabled;
|
|
|
|
self.coinbaseTestnet = configService.getSync().coinbase.testnet;
|
|
|
|
var network = self.coinbaseTestnet ? 'testnet' : 'livenet';
|
|
|
|
|
|
|
|
self.coinbaseToken = null;
|
|
|
|
self.coinbaseError = null;
|
|
|
|
self.coinbasePermissions = null;
|
|
|
|
self.coinbaseEmail = null;
|
|
|
|
self.coinbasePersonalInfo = null;
|
|
|
|
self.coinbaseTxs = null;
|
|
|
|
self.coinbaseStatus = null;
|
|
|
|
|
|
|
|
if (!self.coinbaseEnabled) return;
|
|
|
|
|
|
|
|
coinbaseService.setCredentials(network);
|
|
|
|
|
|
|
|
var getToken = function(cb) {
|
|
|
|
if (accessToken) {
|
|
|
|
cb(null, accessToken);
|
|
|
|
} else {
|
|
|
|
storageService.getCoinbaseToken(network, cb);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
getToken(function(err, accessToken) {
|
|
|
|
if (err || !accessToken) return;
|
|
|
|
else {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('Getting primary account...', true);
|
2016-04-13 10:08:03 -07:00
|
|
|
coinbaseService.getAccounts(accessToken, function(err, a) {
|
2016-06-13 11:25:40 -07:00
|
|
|
ongoingProcess.set('Getting primary account...', false);
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) {
|
|
|
|
self.coinbaseError = err;
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.coinbaseToken = accessToken;
|
|
|
|
lodash.each(a.data, function(account) {
|
|
|
|
if (account.primary && account.type == 'wallet') {
|
|
|
|
self.coinbaseAccount = account;
|
|
|
|
self.updateCoinbase();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
self.updateCoinbase = lodash.debounce(function(opts) {
|
|
|
|
if (!self.coinbaseToken || !self.coinbaseAccount) return;
|
|
|
|
var accessToken = self.coinbaseToken;
|
|
|
|
var accountId = self.coinbaseAccount.id;
|
|
|
|
|
|
|
|
opts = opts || {};
|
|
|
|
|
|
|
|
if (opts.updateAccount) {
|
|
|
|
coinbaseService.getAccount(accessToken, accountId, function(err, a) {
|
|
|
|
if (err) {
|
|
|
|
self.coinbaseError = err;
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.coinbaseAccount = a.data;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
coinbaseService.getCurrentUser(accessToken, function(err, u) {
|
|
|
|
if (err) {
|
|
|
|
self.coinbaseError = err;
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.coinbaseUser = u.data;
|
|
|
|
});
|
|
|
|
|
|
|
|
coinbaseService.getPendingTransactions(function(err, txs) {
|
|
|
|
self.coinbasePendingTransactions = lodash.isEmpty(txs) ? null : txs;
|
|
|
|
lodash.forEach(txs, function(dataFromStorage, txId) {
|
2016-04-29 08:14:09 -07:00
|
|
|
if ((dataFromStorage.type == 'sell' && dataFromStorage.status == 'completed') ||
|
2016-05-20 07:37:13 -07:00
|
|
|
(dataFromStorage.type == 'buy' && dataFromStorage.status == 'completed') ||
|
|
|
|
dataFromStorage.status == 'error' ||
|
|
|
|
(dataFromStorage.type == 'send' && dataFromStorage.status == 'completed')) return;
|
2016-04-13 10:08:03 -07:00
|
|
|
coinbaseService.getTransaction(accessToken, accountId, txId, function(err, tx) {
|
|
|
|
if (err) {
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
return;
|
|
|
|
}
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(dataFromStorage, {
|
|
|
|
status: 'error',
|
|
|
|
error: err
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_updateCoinbasePendingTransactions(dataFromStorage, tx.data);
|
|
|
|
self.coinbasePendingTransactions[txId] = dataFromStorage;
|
|
|
|
if (tx.data.type == 'send' && tx.data.status == 'completed' && tx.data.from) {
|
|
|
|
coinbaseService.sellPrice(accessToken, dataFromStorage.sell_price_currency, function(err, s) {
|
|
|
|
if (err) {
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
return;
|
|
|
|
}
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(dataFromStorage, {
|
|
|
|
status: 'error',
|
|
|
|
error: err
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var newSellPrice = s.data.amount;
|
|
|
|
var variance = Math.abs((newSellPrice - dataFromStorage.sell_price_amount) / dataFromStorage.sell_price_amount * 100);
|
|
|
|
if (variance < dataFromStorage.price_sensitivity.value) {
|
|
|
|
self.sellPending(tx.data);
|
|
|
|
} else {
|
2016-05-20 07:37:13 -07:00
|
|
|
var error = {
|
|
|
|
errors: [{
|
|
|
|
message: 'Price falls over the selected percentage'
|
|
|
|
}]
|
|
|
|
};
|
|
|
|
coinbaseService.savePendingTransaction(dataFromStorage, {
|
|
|
|
status: 'error',
|
|
|
|
error: error
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2016-04-21 13:20:10 -07:00
|
|
|
} else if (tx.data.type == 'buy' && tx.data.status == 'completed' && tx.data.buy) {
|
|
|
|
self.sendToCopay(dataFromStorage);
|
2016-04-13 10:08:03 -07:00
|
|
|
} else {
|
|
|
|
coinbaseService.savePendingTransaction(dataFromStorage, {}, function(err) {
|
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
2016-05-20 07:37:13 -07:00
|
|
|
var _updateCoinbasePendingTransactions = function(obj /*, …*/ ) {
|
|
|
|
for (var i = 1; i < arguments.length; i++) {
|
2016-04-13 10:08:03 -07:00
|
|
|
for (var prop in arguments[i]) {
|
|
|
|
var val = arguments[i][prop];
|
|
|
|
if (typeof val == "object")
|
|
|
|
_updateCoinbasePendingTransactions(obj[prop], val);
|
|
|
|
else
|
|
|
|
obj[prop] = val ? val : obj[prop];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.refreshCoinbaseToken = function() {
|
|
|
|
var network = self.coinbaseTestnet ? 'testnet' : 'livenet';
|
|
|
|
storageService.getCoinbaseRefreshToken(network, function(err, refreshToken) {
|
2016-04-29 06:27:46 -07:00
|
|
|
if (!refreshToken) return;
|
2016-04-13 10:08:03 -07:00
|
|
|
coinbaseService.refreshToken(refreshToken, function(err, data) {
|
|
|
|
if (err) {
|
|
|
|
self.coinbaseError = err;
|
|
|
|
} else if (data && data.access_token && data.refresh_token) {
|
|
|
|
storageService.setCoinbaseToken(network, data.access_token, function() {
|
|
|
|
storageService.setCoinbaseRefreshToken(network, data.refresh_token, function() {
|
|
|
|
$timeout(function() {
|
|
|
|
self.initCoinbase(data.access_token);
|
|
|
|
}, 100);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-04-21 13:20:10 -07:00
|
|
|
self.sendToCopay = function(tx) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (!tx) return;
|
|
|
|
var data = {
|
|
|
|
to: tx.toAddr,
|
|
|
|
amount: tx.amount.amount,
|
|
|
|
currency: tx.amount.currency,
|
|
|
|
description: 'To Copay Wallet'
|
|
|
|
};
|
|
|
|
coinbaseService.sendTo(self.coinbaseToken, self.coinbaseAccount.id, data, function(err, res) {
|
|
|
|
if (err) {
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
return;
|
|
|
|
}
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(tx, {
|
|
|
|
status: 'error',
|
|
|
|
error: err
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
} else {
|
2016-04-29 08:14:09 -07:00
|
|
|
if (!res.data.id) {
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(tx, {
|
|
|
|
status: 'error',
|
|
|
|
error: err
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
coinbaseService.getTransaction(self.coinbaseToken, self.coinbaseAccount.id, res.data.id, function(err, sendTx) {
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(tx, {
|
|
|
|
remove: true
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
coinbaseService.savePendingTransaction(sendTx.data, {}, function(err) {
|
|
|
|
$timeout(function() {
|
2016-05-20 07:37:13 -07:00
|
|
|
self.updateCoinbase({
|
|
|
|
updateAccount: true
|
|
|
|
});
|
2016-04-13 10:08:03 -07:00
|
|
|
}, 1000);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
self.sellPending = function(tx) {
|
|
|
|
if (!tx) return;
|
|
|
|
var data = tx.amount;
|
|
|
|
data['commit'] = true;
|
|
|
|
coinbaseService.sellRequest(self.coinbaseToken, self.coinbaseAccount.id, data, function(err, res) {
|
|
|
|
if (err) {
|
|
|
|
if (err.errors[0] && err.errors[0].id == 'expired_token') {
|
|
|
|
self.refreshCoinbaseToken();
|
|
|
|
return;
|
|
|
|
}
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(tx, {
|
|
|
|
status: 'error',
|
|
|
|
error: err
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if (!res.data.transaction) {
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(tx, {
|
|
|
|
status: 'error',
|
|
|
|
error: err
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
if (err) $log.debug(err);
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2016-05-20 07:37:13 -07:00
|
|
|
coinbaseService.savePendingTransaction(tx, {
|
|
|
|
remove: true
|
|
|
|
}, function(err) {
|
2016-04-13 10:08:03 -07:00
|
|
|
coinbaseService.getTransaction(self.coinbaseToken, self.coinbaseAccount.id, res.data.transaction.id, function(err, updatedTx) {
|
|
|
|
coinbaseService.savePendingTransaction(updatedTx.data, {}, function(err) {
|
|
|
|
if (err) $log.debug(err);
|
|
|
|
$timeout(function() {
|
2016-05-20 07:37:13 -07:00
|
|
|
self.updateCoinbase({
|
|
|
|
updateAccount: true
|
|
|
|
});
|
2016-04-13 10:08:03 -07:00
|
|
|
}, 1000);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2016-04-29 08:14:09 -07:00
|
|
|
});
|
2016-04-13 10:08:03 -07:00
|
|
|
};
|
|
|
|
|
2015-11-02 07:04:18 -08:00
|
|
|
self.setAddressbook = function(ab) {
|
|
|
|
if (ab) {
|
|
|
|
self.addressbook = ab;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-30 14:34:34 -07:00
|
|
|
addressbookService.list(function(err, ab) {
|
|
|
|
if (err) {
|
|
|
|
$log.error('Error getting the addressbook');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.addressbook = ab;
|
2015-11-02 05:50:58 -08:00
|
|
|
});
|
2015-10-30 14:34:34 -07:00
|
|
|
};
|
|
|
|
|
2015-11-23 12:53:42 -08:00
|
|
|
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams) {
|
|
|
|
self.prevState = from.name || 'walletHome';
|
2015-11-24 05:21:29 -08:00
|
|
|
self.tab = 'walletHome';
|
2015-11-23 12:53:42 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 05:50:37 -07:00
|
|
|
$rootScope.$on('Local/ValidatingWallet', function() {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('validatingWallet', true);
|
2016-06-13 05:50:37 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
$rootScope.$on('Local/ProfileBound', function() {
|
2016-06-13 07:44:58 -07:00
|
|
|
ongoingProcess.set('validatingWallet', false);
|
2016-06-13 05:50:37 -07:00
|
|
|
});
|
|
|
|
|
2015-10-30 08:57:38 -07:00
|
|
|
$rootScope.$on('Local/ClearHistory', function(event) {
|
2015-10-30 08:55:41 -07:00
|
|
|
$log.debug('The wallet transaction history has been deleted');
|
2016-02-23 10:50:46 -08:00
|
|
|
self.txHistory = self.completeHistory = self.txHistorySearchResults = [];
|
2015-12-09 06:57:43 -08:00
|
|
|
self.debounceUpdateHistory();
|
2015-10-30 08:47:37 -07:00
|
|
|
});
|
|
|
|
|
2015-11-02 07:04:18 -08:00
|
|
|
$rootScope.$on('Local/AddressbookUpdated', function(event, ab) {
|
|
|
|
self.setAddressbook(ab);
|
2015-10-30 14:34:34 -07:00
|
|
|
});
|
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
// UX event handlers
|
|
|
|
$rootScope.$on('Local/ColorUpdated', function(event) {
|
|
|
|
self.updateColor();
|
2015-04-27 09:11:32 -07:00
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2015-05-14 06:39:22 -07:00
|
|
|
$rootScope.$on('Local/AliasUpdated', function(event) {
|
|
|
|
self.updateAlias();
|
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-12-23 13:05:22 -08:00
|
|
|
$rootScope.$on('Local/SpendUnconfirmedUpdated', function(event, spendUnconfirmed) {
|
|
|
|
self.setSpendUnconfirmed(spendUnconfirmed);
|
2015-08-11 13:45:57 -07:00
|
|
|
self.updateAll();
|
2015-08-03 16:39:09 -07:00
|
|
|
});
|
|
|
|
|
2015-09-11 09:11:41 -07:00
|
|
|
$rootScope.$on('Local/GlideraUpdated', function(event, accessToken) {
|
2015-09-05 10:30:02 -07:00
|
|
|
self.initGlidera(accessToken);
|
|
|
|
});
|
|
|
|
|
2016-04-13 10:08:03 -07:00
|
|
|
$rootScope.$on('Local/CoinbaseUpdated', function(event, accessToken) {
|
|
|
|
self.initCoinbase(accessToken);
|
|
|
|
});
|
|
|
|
|
2015-09-09 06:39:35 -07:00
|
|
|
$rootScope.$on('Local/GlideraTx', function(event, accessToken, permissions) {
|
|
|
|
self.updateGlidera();
|
2015-08-28 14:23:24 -07:00
|
|
|
});
|
|
|
|
|
2016-04-13 10:08:03 -07:00
|
|
|
$rootScope.$on('Local/CoinbaseTx', function(event) {
|
|
|
|
self.updateCoinbase({
|
|
|
|
updateAccount: true
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-09-07 13:43:55 -07:00
|
|
|
$rootScope.$on('Local/GlideraError', function(event) {
|
|
|
|
self.debouncedUpdate();
|
|
|
|
});
|
|
|
|
|
2015-04-25 08:37:04 -07:00
|
|
|
$rootScope.$on('Local/UnitSettingUpdated', function(event) {
|
2015-11-18 05:24:15 -08:00
|
|
|
self.updateAll({
|
|
|
|
triggerTxUpdate: true,
|
|
|
|
});
|
2015-05-19 10:10:47 -07:00
|
|
|
});
|
|
|
|
|
2016-03-09 06:53:47 -08:00
|
|
|
$rootScope.$on('Local/WalletCompleted', function(event, walletId) {
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
if (fc && fc.credentials.walletId == walletId) {
|
|
|
|
// reset main wallet variables
|
|
|
|
self.setFocusedWallet();
|
|
|
|
go.walletHome();
|
|
|
|
}
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2016-06-11 09:52:44 -07:00
|
|
|
self.debouncedUpdate = function() {
|
|
|
|
var now = Date.now();
|
|
|
|
var oneHr = 1000 * 60 * 60;
|
|
|
|
|
|
|
|
if (!self.lastUpdate || (now - self.lastUpdate) > oneHr) {
|
|
|
|
self.updateAll({
|
2016-06-11 14:28:31 -07:00
|
|
|
quiet: true,
|
|
|
|
triggerTxUpdate: true
|
2016-06-11 09:52:44 -07:00
|
|
|
});
|
|
|
|
}
|
2016-06-11 14:28:31 -07:00
|
|
|
};
|
2015-04-28 15:26:22 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/Resume', function(event) {
|
|
|
|
$log.debug('### Resume event');
|
|
|
|
profileService.isDisclaimerAccepted(function(v) {
|
|
|
|
if (!v) {
|
|
|
|
$log.debug('Disclaimer not accepted, resume to home');
|
|
|
|
go.path('disclaimer');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
self.debouncedUpdate();
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/BackupDone', function(event, walletId) {
|
|
|
|
self.needsBackup = false;
|
|
|
|
$log.debug('Backup done');
|
|
|
|
storageService.setBackupFlag(walletId || self.walletId, function(err) {
|
|
|
|
$log.debug('Backup stored');
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/DeviceError', function(event, err) {
|
|
|
|
self.showErrorPopup(err, function() {
|
|
|
|
if (isCordova && navigator && navigator.app) {
|
|
|
|
navigator.app.exitApp();
|
|
|
|
}
|
2015-04-18 03:23:11 -07:00
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/WalletImported', function(event, walletId) {
|
|
|
|
self.needsBackup = false;
|
|
|
|
storageService.setBackupFlag(walletId, function() {
|
|
|
|
$log.debug('Backup done stored');
|
|
|
|
addressService.expireAddress(walletId, function(err) {
|
|
|
|
$timeout(function() {
|
|
|
|
self.txHistory = self.completeHistory = self.txHistorySearchResults = [];
|
|
|
|
storageService.removeTxHistory(walletId, function() {
|
|
|
|
self.startScan(walletId);
|
|
|
|
});
|
|
|
|
}, 500);
|
|
|
|
});
|
|
|
|
});
|
2016-06-11 09:52:44 -07:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('NewIncomingTx', function() {
|
|
|
|
self.newTx = true;
|
2015-07-06 06:40:40 -07:00
|
|
|
self.updateAll({
|
|
|
|
walletStatus: null,
|
2016-06-13 07:44:58 -07:00
|
|
|
untilItChanges: true,
|
2015-07-06 06:40:40 -07:00
|
|
|
triggerTxUpdate: true,
|
|
|
|
});
|
2016-06-13 07:44:58 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$rootScope.$on('NewBlock', function() {
|
|
|
|
if (self.glideraEnabled) {
|
|
|
|
$timeout(function() {
|
|
|
|
self.updateGlidera();
|
|
|
|
});
|
2015-08-12 04:57:44 -07:00
|
|
|
}
|
2016-06-13 07:44:58 -07:00
|
|
|
if (self.coinbaseEnabled) {
|
|
|
|
$timeout(function() {
|
|
|
|
self.updateCoinbase();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (self.pendingAmount) {
|
|
|
|
self.updateAll({
|
|
|
|
walletStatus: null,
|
|
|
|
untilItChanges: null,
|
|
|
|
triggerTxUpdate: true,
|
|
|
|
});
|
|
|
|
} else if (self.hasUnsafeConfirmed) {
|
|
|
|
$log.debug('Wallet has transactions with few confirmations. Updating.')
|
|
|
|
if (self.network == 'testnet') {
|
|
|
|
self.throttledUpdateHistory();
|
|
|
|
} else {
|
|
|
|
self.debounceUpdateHistory();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2015-08-12 04:57:44 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('BalanceUpdated', function(e, n) {
|
|
|
|
self.setBalance(n.data);
|
|
|
|
});
|
2016-03-09 06:53:47 -08:00
|
|
|
|
2015-05-29 08:39:17 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
//untilItChange TRUE
|
|
|
|
lodash.each(['NewOutgoingTx', 'NewOutgoingTxByThirdParty'], function(eventName) {
|
|
|
|
$rootScope.$on(eventName, function(event) {
|
|
|
|
self.newTx = true;
|
|
|
|
self.updateAll({
|
|
|
|
walletStatus: null,
|
|
|
|
untilItChanges: true,
|
|
|
|
triggerTxUpdate: true,
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
//untilItChange FALSE
|
|
|
|
lodash.each(['NewTxProposal', 'TxProposalFinallyRejected', 'TxProposalRemoved', 'NewOutgoingTxByThirdParty',
|
|
|
|
'Local/GlideraTx'
|
|
|
|
], function(eventName) {
|
|
|
|
$rootScope.$on(eventName, function(event) {
|
|
|
|
self.updateAll({
|
|
|
|
walletStatus: null,
|
|
|
|
untilItChanges: null,
|
|
|
|
triggerTxUpdate: true,
|
|
|
|
});
|
2016-03-09 06:53:47 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-11 09:52:44 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
//untilItChange Maybe
|
|
|
|
$rootScope.$on('Local/TxProposalAction', function(event, untilItChanges) {
|
|
|
|
self.newTx = untilItChanges;
|
2016-06-11 09:52:44 -07:00
|
|
|
self.updateAll({
|
|
|
|
walletStatus: null,
|
2016-06-13 07:44:58 -07:00
|
|
|
untilItChanges: untilItChanges,
|
2016-06-11 09:52:44 -07:00
|
|
|
triggerTxUpdate: true,
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('ScanFinished', function() {
|
|
|
|
$log.debug('Scan Finished. Updating history');
|
|
|
|
storageService.removeTxHistory(self.walletId, function() {
|
|
|
|
self.updateAll({
|
|
|
|
walletStatus: null,
|
|
|
|
triggerTxUpdate: true,
|
|
|
|
});
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
lodash.each(['TxProposalRejectedBy', 'TxProposalAcceptedBy'], function(eventName) {
|
|
|
|
$rootScope.$on(eventName, function() {
|
|
|
|
var f = function() {
|
|
|
|
if (self.updatingStatus) {
|
|
|
|
return $timeout(f, 200);
|
|
|
|
};
|
|
|
|
self.updatePendingTxps();
|
|
|
|
};
|
|
|
|
f();
|
|
|
|
});
|
|
|
|
});
|
2016-03-09 11:10:44 -08:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/NoWallets', function(event) {
|
|
|
|
$timeout(function() {
|
|
|
|
self.hasProfile = true;
|
|
|
|
self.noFocusedWallet = true;
|
|
|
|
self.isComplete = null;
|
|
|
|
self.walletName = null;
|
|
|
|
uxLanguage.update();
|
|
|
|
|
|
|
|
profileService.isDisclaimerAccepted(function(v) {
|
|
|
|
if (v) {
|
|
|
|
go.path('import');
|
|
|
|
}
|
|
|
|
});
|
2015-12-05 15:50:31 -08:00
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/NewFocusedWallet', function() {
|
|
|
|
uxLanguage.update();
|
|
|
|
self.setFocusedWallet();
|
|
|
|
self.updateHistory();
|
|
|
|
storageService.getCleanAndScanAddresses(function(err, walletId) {
|
2016-06-11 09:52:44 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
if (walletId && profileService.walletClients[walletId]) {
|
|
|
|
$log.debug('Clear last address cache and Scan ', walletId);
|
|
|
|
addressService.expireAddress(walletId, function(err) {
|
|
|
|
self.startScan(walletId);
|
|
|
|
});
|
|
|
|
storageService.removeCleanAndScanAddresses(function() {
|
|
|
|
$rootScope.$emit('Local/NewFocusedWalletReady');
|
|
|
|
});
|
|
|
|
} else {
|
2016-06-11 09:52:44 -07:00
|
|
|
$rootScope.$emit('Local/NewFocusedWalletReady');
|
2016-06-13 07:44:58 -07:00
|
|
|
}
|
|
|
|
});
|
2015-04-23 10:37:44 -07:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/SetTab', function(event, tab, reset) {
|
|
|
|
self.setTab(tab, reset);
|
|
|
|
});
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/NeedsConfirmation', function(event, txp, cb) {
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
function openConfirmationPopup(txp, cb) {
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.tx = txFormatService.processTx(txp);
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
self.confirmationPopup = $ionicPopup.show({
|
|
|
|
templateUrl: 'views/includes/confirm-tx.html',
|
|
|
|
scope: $scope,
|
|
|
|
});
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.processFee = function(amount, fee) {
|
|
|
|
var walletSettings = configService.getSync().wallet.settings;
|
|
|
|
var feeAlternativeIsoCode = walletSettings.alternativeIsoCode;
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.feeLevel = feeService.feeOpts[feeService.getCurrentFeeLevel()];
|
|
|
|
$scope.feeAlternativeStr = parseFloat((rateService.toFiat(fee, feeAlternativeIsoCode)).toFixed(2), 10) + ' ' + feeAlternativeIsoCode;
|
|
|
|
$scope.feeRateStr = (fee / (amount + fee) * 100).toFixed(2) + '%';
|
|
|
|
};
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.cancel = function() {
|
|
|
|
return cb();
|
|
|
|
};
|
2016-06-04 11:19:42 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.accept = function() {
|
|
|
|
return cb(true);
|
|
|
|
};
|
|
|
|
}
|
2016-06-11 09:52:44 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
openConfirmationPopup(txp, function(accept) {
|
|
|
|
self.confirmationPopup.close();
|
|
|
|
return cb(accept);
|
|
|
|
});
|
2016-01-27 11:41:12 -08:00
|
|
|
});
|
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) {
|
2016-06-03 07:30:04 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
function openPasswordPopup(isSetup, cb) {
|
|
|
|
$scope.data = {};
|
|
|
|
$scope.data.password = null;
|
|
|
|
$scope.isSetup = isSetup;
|
|
|
|
$scope.isVerification = false;
|
|
|
|
$scope.loading = false;
|
|
|
|
var pass = null;
|
2016-06-03 07:30:04 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
self.passwordPopup = $ionicPopup.show({
|
|
|
|
templateUrl: 'views/includes/password.html',
|
|
|
|
scope: $scope,
|
|
|
|
});
|
2016-06-03 07:30:04 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.cancel = function() {
|
|
|
|
return cb('No spending password given');
|
|
|
|
};
|
2016-06-03 07:30:04 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$scope.set = function() {
|
|
|
|
$scope.loading = true;
|
|
|
|
$scope.error = null;
|
2016-06-03 07:30:04 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$timeout(function() {
|
|
|
|
if (isSetup && !$scope.isVerification) {
|
|
|
|
$scope.loading = false;
|
|
|
|
$scope.isVerification = true;
|
|
|
|
pass = $scope.data.password;
|
|
|
|
$scope.data.password = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (isSetup && pass != $scope.data.password) {
|
|
|
|
$scope.loading = false;
|
|
|
|
$scope.error = gettext('Spending Passwords do not match');
|
|
|
|
$scope.isVerification = false;
|
|
|
|
$scope.data.password = null;
|
|
|
|
pass = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return cb(null, $scope.data.password);
|
|
|
|
}, 100);
|
|
|
|
};
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
2016-06-03 07:30:04 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
openPasswordPopup(isSetup, function(err, pass) {
|
|
|
|
self.passwordPopup.close();
|
|
|
|
return cb(err, pass);
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
});
|
2016-06-06 14:26:45 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/EmailUpdated', function(event, email) {
|
|
|
|
self.preferences.email = email;
|
|
|
|
});
|
2016-06-11 09:52:44 -07:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
lodash.each(['NewCopayer', 'CopayerUpdated'], function(eventName) {
|
|
|
|
$rootScope.$on(eventName, function() {
|
|
|
|
// Re try to open wallet (will triggers)
|
|
|
|
self.setFocusedWallet();
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|
2015-11-10 15:05:05 -08:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
$rootScope.$on('Local/NewEncryptionSetting', function() {
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
self.isPrivKeyEncrypted = fc.isPrivKeyEncrypted();
|
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
2015-11-10 15:05:05 -08:00
|
|
|
});
|
2016-01-15 06:59:29 -08:00
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
|
2016-06-13 07:44:58 -07:00
|
|
|
/* Start setup */
|
|
|
|
lodash.assign(self, vanillaScope);
|
|
|
|
openURLService.init();
|
2015-11-02 07:04:18 -08:00
|
|
|
});
|