diff --git a/old/go.js b/old/go.js deleted file mode 100644 index 932b9d9ae..000000000 --- a/old/go.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -angular.module('copayApp.services').factory('go', function($window, $ionicSideMenuDelegate, $rootScope, $location, $state, $timeout, $log, profileService, platformInfo, nodeWebkit) { - var root = {}; - - root.openExternalLink = function(url, target) { - if (platformInfo.isNW) { - nodeWebkit.openExternalLink(url); - } else { - target = target || '_blank'; - var ref = window.open(url, target, 'location=no'); - } - }; - - root.is = function(name) { - return $state.is(name); - }; - - root.path = function(path, cb) { - $state.transitionTo(path) - .then(function() { - if (cb) return cb(); - }, function() { - if (cb) return cb('animation in progress'); - }); - }; - - root.toggleLeftMenu = function() { - $ionicSideMenuDelegate.toggleLeft(); - }; - - root.walletHome = function() { - var wallet = profileService.getWallet($stateParams.walletId); - if (wallet && !wallet.isComplete()) { - $log.debug("Wallet not complete at startup... redirecting"); - $state.transitionTo('wallet.details', { - walletId: wallet.credentials.walletId - }) - } else { - root.path('tabs.home'); - } - }; - - root.confirm = function(params) { - $state.transitionTo('send.confirm', params) - }; - - root.send = function() { - root.path('tabs.send'); - }; - - root.addWallet = function() { - $state.transitionTo('add'); - }; - - root.preferences = function() { - $state.transitionTo('preferences'); - }; - - root.preferencesGlobal = function() { - $state.transitionTo('tabs.settings'); - }; - - root.reload = function() { - $state.reload(); - }; - - - // Global go. This should be in a better place TODO - // We don't do a 'go' directive, to use the benefits of ng-touch with ng-click - $rootScope.go = function(path) { - root.path(path); - }; - - $rootScope.openExternalLink = function(url, target) { - root.openExternalLink(url, target); - }; - - - - return root; -}); diff --git a/old/index.js b/old/index.js deleted file mode 100644 index 71cdeed98..000000000 --- a/old/index.js +++ /dev/null @@ -1,1338 +0,0 @@ -'use strict'; - -angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, $ionicScrollDelegate, $ionicPopup, $ionicSideMenuDelegate, $httpBackend, latestReleaseService, feeService, bwcService, pushNotificationsService, lodash, go, profileService, configService, rateService, storageService, addressService, gettext, gettextCatalog, amMoment, addonManager, bwcError, txFormatService, uxLanguage, glideraService, coinbaseService, platformInfo, addressbookService, openURLService, ongoingProcess) { - - var self = this; - var SOFT_CONFIRMATION_LIMIT = 12; - var errors = bwcService.getErrors(); - var historyUpdateInProgress = {}; - var isChromeApp = platformInfo.isChromeApp; - var isCordova = platformInfo.isCordova; - var isNW = platformInfo.isNW; - - var ret = {}; - ret.isCordova = isCordova; - ret.isChromeApp = isChromeApp; - ret.isSafari = platformInfo.isSafari; - ret.isWindowsPhoneApp = platformInfo.isWP; - ret.historyShowLimit = 10; - ret.historyShowMoreLimit = 10; - ret.isSearching = false; - ret.prevState = 'walletHome'; - ret.physicalScreenWidth = ((window.innerWidth > 0) ? window.innerWidth : screen.width); - - ret.appConfig = window.appConfig; - - // Only for testing - //storageService.checkQuota(); - - ret.menu = [{ - 'title': gettext('Receive'), - 'icon': { - false: 'icon-receive', - true: 'icon-receive-active' - }, - 'link': 'receive' - }, { - 'title': gettext('Activity'), - 'icon': { - false: 'icon-activity', - true: 'icon-activity-active' - }, - 'link': 'walletHome' - }, { - 'title': gettext('Send'), - 'icon': { - false: 'icon-send', - true: 'icon-send-active' - }, - 'link': 'send' - }]; - - ret.addonViews = addonManager.addonViews(); - ret.txTemplateUrl = addonManager.txTemplateUrl() || 'views/includes/transaction.html'; - - ret.tab = 'walletHome'; - var vanillaScope = ret; - - if (isNW) { - 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'); - }); - } - - function strip(number) { - return (parseFloat(number.toPrecision(12))); - }; - - self.goHome = function() { - go.walletHome(); - }; - - self.allowRefresher = function() { - if ($ionicSideMenuDelegate.getOpenRatio() != 0) self.allowPullToRefresh = false; - } - - self.hideBalance = function() { - storageService.getHideBalanceFlag(self.walletId, function(err, shouldHideBalance) { - if (err) self.shouldHideBalance = false; - else self.shouldHideBalance = (shouldHideBalance == 'true') ? true : false; - }); - } - - self.onHold = function() { - self.shouldHideBalance = !self.shouldHideBalance; - storageService.setHideBalanceFlag(self.walletId, self.shouldHideBalance.toString(), function() {}); - } - - self.setWalletPreferencesTitle = function() { - return gettext("Wallet Preferences"); - } - - 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; - if (k == 'tab') return; - if (k == 'noFocusedWallet') return; - if (k == 'backgroundColor') return; - if (k == 'physicalScreenWidth') return; - if (k == 'loadingWallet') { - self.loadingWallet = true; - return; - } - if (!lodash.isUndefined(vanillaScope[k])) { - self[k] = vanillaScope[k]; - return; - } - - delete self[k]; - }); - }; - - self.setFocusedWallet = function() { - var fc = profileService.focusedClient; - if (!fc) return; - - self.cleanInstance(); - self.loadingWallet = true; - self.setSpendUnconfirmed(); - - $timeout(function() { - $rootScope.$apply(); - - self.hasProfile = true; - self.isSingleAddress = false; - self.noFocusedWallet = false; - self.updating = false; - - // Credentials Shortcuts - 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(); - self.canSign = fc.canSign(); - self.isPrivKeyExternal = fc.isPrivKeyExternal(); - self.isPrivKeyEncrypted = fc.isPrivKeyEncrypted(); - self.externalSource = fc.getPrivKeyExternalSourceName(); - self.account = fc.credentials.account; - self.incorrectDerivation = fc.keyDerivationOk === false; - - if (self.externalSource == 'trezor') - self.account++; - - self.txps = []; - self.copayers = []; - self.updateColor(); - self.updateAlias(); - self.setAddressbook(); - - self.initGlidera(); - self.initCoinbase(); - - self.hideBalance(); - - self.setCustomBWSFlag(); - - if (!self.isComplete) { - $log.debug('Wallet not complete BEFORE update... redirecting'); - go.path('copayers'); - } else { - if (go.is('copayers')) { - $log.debug('Wallet Complete BEFORE update... redirect to home'); - go.walletHome(); - } - } - - profileService.needsBackup(fc, function(needsBackup) { - self.needsBackup = needsBackup; - self.openWallet(function() { - if (!self.isComplete) { - $log.debug('Wallet not complete after update... redirecting'); - go.path('copayers'); - } else { - if (go.is('copayers')) { - $log.debug('Wallet Complete after update... redirect to home'); - go.walletHome(); - } - } - }); - }); - }); - }; - - self.setCustomBWSFlag = function() { - var defaults = configService.getDefaults(); - var config = configService.getSync(); - - self.usingCustomBWS = config.bwsFor && config.bwsFor[self.walletId] && (config.bwsFor[self.walletId] != defaults.bws.url); - }; - - - self.setTab = function(tab, reset, tries, switchState) { - tries = tries || 0; - - // 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); - } - } - if (self.tab === tab && !reset) - return; - - if (!document.getElementById('menu-' + tab) && ++tries < 5) { - return $timeout(function() { - self.setTab(tab, reset, tries, switchState); - }, 300); - } - - if (!self.tab || !go.is('walletHome')) - self.tab = 'walletHome'; - - 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 = ''; - } - } - - if (document.getElementById(tab)) { - document.getElementById(tab).className = 'tab-in tab-view ' + tab; - var newe = document.getElementById('menu-' + tab); - if (newe) { - newe.className = 'active'; - } - } - - self.tab = tab; - $rootScope.$emit('Local/TabChanged', tab); - }; - - if (switchState && !go.is('walletHome')) { - go.path('walletHome', function() { - changeTab(); - }); - return; - } - - changeTab(); - }; - - - self.setSpendUnconfirmed = function(spendUnconfirmed) { - self.spendUnconfirmed = spendUnconfirmed || configService.getSync().wallet.spendUnconfirmed; - }; - - self.updateBalance = function() { - var fc = profileService.focusedClient; - $timeout(function() { - ongoingProcess.set('updatingBalance', true); - $log.debug('Updating Balance'); - fc.getBalance(function(err, balance) { - ongoingProcess.set('updatingBalance', false); - if (err) { - self.handleError(err); - return; - } - $log.debug('Wallet Balance:', balance); - self.setBalance(balance); - }); - }); - }; - - self.updatePendingTxps = function() { - var fc = profileService.focusedClient; - $timeout(function() { - self.updating = true; - $log.debug('Updating PendingTxps'); - fc.getTxProposals({}, function(err, txps) { - self.updating = false; - if (err) { - self.handleError(err); - } else { - $log.debug('Wallet PendingTxps:', txps); - self.setPendingTxps(txps); - } - $rootScope.$apply(); - }); - }); - }; - - // 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); - 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); - } - }; - - self.handleError = lodash.debounce(_handleError, 1000); - - self.openWallet = function(cb) { - var fc = profileService.focusedClient; - $timeout(function() { - $rootScope.$apply(); - self.updating = true; - self.updateError = false; - fc.openWallet(function(err, walletStatus) { - self.updating = false; - if (err) { - self.updateError = true; - self.handleError(err); - return; - } - $log.debug('Wallet Opened'); - - self.updateAll(lodash.isObject(walletStatus) ? { - walletStatus: walletStatus, - cb: cb, - } : { - cb: cb - }); - $rootScope.$apply(); - }); - }); - }; - - self.setPendingTxps = function(txps) { - self.pendingTxProposalsCountForUs = 0; - var now = Math.floor(Date.now() / 1000); - - /* 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); - */ - - lodash.each(txps, function(tx) { - - tx = txFormatService.processTx(tx); - - // no future transactions... - if (tx.createdOn > now) - tx.createdOn = now; - - 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'; - } - - if (!tx.deleteLockTime) - tx.canBeRemoved = true; - - if (tx.creatorId != self.copayerId) { - self.pendingTxProposalsCountForUs = self.pendingTxProposalsCountForUs + 1; - } - addonManager.formatPendingTxp(tx); - }); - self.txps = txps; - }; - - var SAFE_CONFIRMATIONS = 6; - - self.processNewTxs = function(txs) { - var config = configService.getSync().wallet.settings; - var now = Math.floor(Date.now() / 1000); - var txHistoryUnique = {}; - var ret = []; - self.hasUnsafeConfirmed = false; - - lodash.each(txs, function(tx) { - tx = txFormatService.processTx(tx); - - // no future transactions... - if (tx.time > now) - tx.time = now; - - if (tx.confirmations >= SAFE_CONFIRMATIONS) { - tx.safeConfirmed = SAFE_CONFIRMATIONS + '+'; - } else { - tx.safeConfirmed = false; - self.hasUnsafeConfirmed = true; - } - - if (tx.note) { - delete tx.note.encryptedEditedByName; - delete tx.note.encryptedBody; - } - - if (!txHistoryUnique[tx.txid]) { - ret.push(tx); - txHistoryUnique[tx.txid] = true; - } else { - $log.debug('Ignoring duplicate TX in history: ' + tx.txid) - } - }); - - return ret; - }; - - 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; - }; - - self.updateColor = function() { - var config = configService.getSync(); - config.colorFor = config.colorFor || {}; - self.backgroundColor = config.colorFor[self.walletId] || '#4A90E2'; - var fc = profileService.focusedClient; - fc.backgroundColor = self.backgroundColor; - if (isCordova && StatusBar.isVisible) { - StatusBar.backgroundColorByHexString(fc.backgroundColor); - } - }; - - self.setBalance = function(balance) { - if (!balance) return; - var config = configService.getSync().wallet.settings; - var COIN = 1e8; - - - // Address with Balance - self.balanceByAddress = balance.byAddress; - - // Spend unconfirmed funds - if (self.spendUnconfirmed) { - self.totalBalanceSat = balance.totalAmount; - self.lockedBalanceSat = balance.lockedAmount; - self.availableBalanceSat = balance.availableAmount; - self.totalBytesToSendMax = balance.totalBytesToSendMax; - self.pendingAmount = null; - } else { - self.totalBalanceSat = balance.totalConfirmedAmount; - self.lockedBalanceSat = balance.lockedConfirmedAmount; - self.availableBalanceSat = balance.availableConfirmedAmount; - self.totalBytesToSendMax = balance.totalBytesToSendConfirmedMax; - self.pendingAmount = balance.totalAmount - balance.totalConfirmedAmount; - } - - // 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; - - if (self.pendingAmount) { - self.pendingAmountStr = profileService.formatAmount(self.pendingAmount) + ' ' + self.unitName; - } else { - self.pendingAmountStr = null; - } - - self.alternativeName = config.alternativeName; - self.alternativeIsoCode = config.alternativeIsoCode; - - // Check address - addressService.isUsed(self.walletId, balance.byAddress, function(err, used) { - if (used) { - $log.debug('Address used. Creating new'); - $rootScope.$emit('Local/AddressIsUsed'); - } - }); - - rateService.whenAvailable(function() { - - var totalBalanceAlternative = rateService.toFiat(self.totalBalanceSat, self.alternativeIsoCode); - var lockedBalanceAlternative = rateService.toFiat(self.lockedBalanceSat, self.alternativeIsoCode); - var alternativeConversionRate = rateService.toFiat(100000000, self.alternativeIsoCode); - - self.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative); - self.lockedBalanceAlternative = $filter('formatFiatAmount')(lockedBalanceAlternative); - self.alternativeConversionRate = $filter('formatFiatAmount')(alternativeConversionRate); - - self.alternativeBalanceAvailable = true; - - self.isRateAvailable = true; - $rootScope.$apply(); - }); - - if (!rateService.isAvailable()) { - $rootScope.$apply(); - } - }; - - - self.showMore = function() { - $timeout(function() { - if (self.isSearching) { - 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); - $log.debug('Total txs: ', self.txHistory.length + '/' + self.completeHistory.length); - if (self.txHistory.length >= self.completeHistory.length) - self.historyShowMore = false; - } - self.nextTxHistory += self.historyShowMoreLimit; - $scope.$broadcast('scroll.infiniteScrollComplete'); - }, 100); - }; - - - - - self.toggleLeftMenu = function() { - profileService.isDisclaimerAccepted(function(val) { - if (val) go.toggleLeftMenu(); - else - $log.debug('Disclaimer not accepted, cannot open menu'); - }); - }; - - self.initGlidera = function(accessToken) { - self.glideraEnabled = configService.getSync().glidera.enabled; - self.glideraTestnet = configService.getSync().glidera.testnet; - var network = self.glideraTestnet ? 'testnet' : 'livenet'; - - self.glideraToken = null; - self.glideraError = null; - self.glideraPermissions = null; - self.glideraEmail = null; - self.glideraPersonalInfo = null; - self.glideraTxs = null; - self.glideraStatus = null; - - if (!self.glideraEnabled) return; - - glideraService.setCredentials(network); - - var getToken = function(cb) { - if (accessToken) { - cb(null, accessToken); - } else { - storageService.getGlideraToken(network, cb); - } - }; - - getToken(function(err, accessToken) { - if (err || !accessToken) return; - else { - glideraService.getAccessTokenPermissions(accessToken, function(err, p) { - if (err) { - self.glideraError = err; - } else { - self.glideraToken = accessToken; - self.glideraPermissions = p; - self.updateGlidera({ - fullUpdate: true - }); - } - }); - } - }); - }; - - self.updateGlidera = function(opts) { - if (!self.glideraToken || !self.glideraPermissions) return; - var accessToken = self.glideraToken; - var permissions = self.glideraPermissions; - - opts = opts || {}; - - glideraService.getStatus(accessToken, function(err, data) { - self.glideraStatus = data; - }); - - glideraService.getLimits(accessToken, function(err, limits) { - self.glideraLimits = limits; - }); - - if (permissions.transaction_history) { - glideraService.getTransactions(accessToken, function(err, data) { - self.glideraTxs = data; - }); - } - - if (permissions.view_email_address && opts.fullUpdate) { - glideraService.getEmail(accessToken, function(err, data) { - self.glideraEmail = data.email; - }); - } - if (permissions.personal_info && opts.fullUpdate) { - glideraService.getPersonalInfo(accessToken, function(err, data) { - self.glideraPersonalInfo = data; - }); - } - - }; - - 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 { - coinbaseService.getAccounts(accessToken, function(err, a) { - 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) { - if ((dataFromStorage.type == 'sell' && dataFromStorage.status == 'completed') || - (dataFromStorage.type == 'buy' && dataFromStorage.status == 'completed') || - dataFromStorage.status == 'error' || - (dataFromStorage.type == 'send' && dataFromStorage.status == 'completed')) return; - coinbaseService.getTransaction(accessToken, accountId, txId, function(err, tx) { - if (err) { - if (err.errors[0] && err.errors[0].id == 'expired_token') { - self.refreshCoinbaseToken(); - return; - } - coinbaseService.savePendingTransaction(dataFromStorage, { - status: 'error', - error: err - }, function(err) { - 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; - } - coinbaseService.savePendingTransaction(dataFromStorage, { - status: 'error', - error: err - }, function(err) { - 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 { - var error = { - errors: [{ - message: 'Price falls over the selected percentage' - }] - }; - coinbaseService.savePendingTransaction(dataFromStorage, { - status: 'error', - error: error - }, function(err) { - if (err) $log.debug(err); - }); - } - }); - } else if (tx.data.type == 'buy' && tx.data.status == 'completed' && tx.data.buy) { - self.sendToCopay(dataFromStorage); - } else { - coinbaseService.savePendingTransaction(dataFromStorage, {}, function(err) { - if (err) $log.debug(err); - }); - } - }); - }); - }); - - }, 1000); - - var _updateCoinbasePendingTransactions = function(obj /*, …*/ ) { - for (var i = 1; i < arguments.length; i++) { - 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) { - if (!refreshToken) return; - 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); - }); - }); - } - }); - }); - }; - - self.sendToCopay = function(tx) { - 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; - } - coinbaseService.savePendingTransaction(tx, { - status: 'error', - error: err - }, function(err) { - if (err) $log.debug(err); - }); - } else { - if (!res.data.id) { - coinbaseService.savePendingTransaction(tx, { - status: 'error', - error: err - }, function(err) { - if (err) $log.debug(err); - }); - return; - } - coinbaseService.getTransaction(self.coinbaseToken, self.coinbaseAccount.id, res.data.id, function(err, sendTx) { - coinbaseService.savePendingTransaction(tx, { - remove: true - }, function(err) { - coinbaseService.savePendingTransaction(sendTx.data, {}, function(err) { - $timeout(function() { - self.updateCoinbase({ - updateAccount: true - }); - }, 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; - } - coinbaseService.savePendingTransaction(tx, { - status: 'error', - error: err - }, function(err) { - if (err) $log.debug(err); - }); - } else { - if (!res.data.transaction) { - coinbaseService.savePendingTransaction(tx, { - status: 'error', - error: err - }, function(err) { - if (err) $log.debug(err); - }); - return; - } - coinbaseService.savePendingTransaction(tx, { - remove: true - }, function(err) { - 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() { - self.updateCoinbase({ - updateAccount: true - }); - }, 1000); - }); - }); - }); - } - }); - }; - - self.isInFocus = function(walletId) { - var fc = profileService.focusedClient; - return fc && fc.credentials.walletId == walletId; - }; - - self.setAddressbook = function(ab) { - if (ab) { - self.addressbook = ab; - return; - } - - addressbookService.list(function(err, ab) { - if (err) { - $log.error('Error getting the addressbook'); - return; - } - self.addressbook = ab; - }); - }; - - $rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams) { - self.prevState = from.name || 'walletHome'; - self.tab = 'walletHome'; - }); - - $rootScope.$on('Local/ValidatingWalletEnded', function(ev, walletId, isOK) { - - if (self.isInFocus(walletId)) { - // NOTE: If the user changed the wallet, the flag is already turn off. - self.incorrectDerivation = isOK === false; - } - }); - - $rootScope.$on('Local/ClearHistory', function(event) { - $log.debug('The wallet transaction history has been deleted'); - self.txHistory = self.completeHistory = self.txHistorySearchResults = []; - self.debounceUpdateHistory(); - }); - - $rootScope.$on('Local/AddressbookUpdated', function(event, ab) { - self.setAddressbook(ab); - }); - - // UX event handlers - $rootScope.$on('Local/ColorUpdated', function(event) { - self.updateColor(); - $timeout(function() { - $rootScope.$apply(); - }); - }); - - $rootScope.$on('Local/AliasUpdated', function(event) { - self.updateAlias(); - $timeout(function() { - $rootScope.$apply(); - }); - }); - - $rootScope.$on('Local/SpendUnconfirmedUpdated', function(event, spendUnconfirmed) { - self.setSpendUnconfirmed(spendUnconfirmed); - self.updateAll(); - }); - - $rootScope.$on('Local/GlideraUpdated', function(event, accessToken) { - self.initGlidera(accessToken); - }); - - $rootScope.$on('Local/CoinbaseUpdated', function(event, accessToken) { - self.initCoinbase(accessToken); - }); - - $rootScope.$on('Local/GlideraTx', function(event, accessToken, permissions) { - self.updateGlidera(); - }); - - $rootScope.$on('Local/CoinbaseTx', function(event) { - self.updateCoinbase({ - updateAccount: true - }); - }); - - $rootScope.$on('Local/GlideraError', function(event) { - self.debouncedUpdate(); - }); - - $rootScope.$on('Local/UnitSettingUpdated', function(event) { - self.updateAll({ - triggerTxUpdate: true, - }); - }); - - $rootScope.$on('Local/WalletCompleted', function(event, walletId) { - if (self.isInFocus(walletId)) { - // reset main wallet variables - self.setFocusedWallet(); - go.walletHome(); - } - }); - - self.debouncedUpdate = function() { - var now = Date.now(); - var oneHr = 1000 * 60 * 60; - - if (!self.lastUpdate || (now - self.lastUpdate) > oneHr) { - self.updateAll({ - quiet: true, - triggerTxUpdate: true - }); - } - }; - - $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(); - }); - - $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'); - }); - }); - - $rootScope.$on('Local/DeviceError', function(event, err) { - self.showErrorPopup(err, function() { - if (isCordova && navigator && navigator.app) { - navigator.app.exitApp(); - } - }); - }); - - $rootScope.$on('Local/WalletImported', function(event, walletId) { -console.log('[index.js:1063] walletImported'); //TODO - return; - 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); - }); - }); - }); - - $rootScope.$on('NewIncomingTx', function() { - self.newTx = true; - self.updateAll({ - walletStatus: null, - untilItChanges: true, - triggerTxUpdate: true, - }); - }); - - - $rootScope.$on('NewBlock', function() { - if (self.glideraEnabled) { - $timeout(function() { - self.updateGlidera(); - }); - } - 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(); - } - } - }); - - $rootScope.$on('BalanceUpdated', function(e, n) { - self.setBalance(n.data); - }); - - - //untilItChange TRUE - lodash.each(['NewOutgoingTx', 'NewOutgoingTxByThirdParty'], function(eventName) { - $rootScope.$on(eventName, function(event) { - self.newTx = true; - self.updateAll({ - walletStatus: null, - untilItChanges: true, - triggerTxUpdate: true, - }); - }); - }); - - //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, - }); - }); - }); - - - //untilItChange Maybe - $rootScope.$on('Local/TxProposalAction', function(event, untilItChanges) { - self.newTx = untilItChanges; - self.updateAll({ - walletStatus: null, - untilItChanges: untilItChanges, - triggerTxUpdate: true, - }); - }); - - $rootScope.$on('ScanFinished', function() { - $log.debug('Scan Finished. Updating history'); - storageService.removeTxHistory(self.walletId, function() { - self.updateAll({ - walletStatus: null, - triggerTxUpdate: true, - }); - }); - }); - - lodash.each(['TxProposalRejectedBy', 'TxProposalAcceptedBy'], function(eventName) { - $rootScope.$on(eventName, function() { - var f = function() { - if (self.updating) { - return $timeout(f, 200); - }; - self.updatePendingTxps(); - }; - f(); - }); - }); - - $rootScope.$on('Local/NoWallets', function(event) { - $timeout(function() { - self.hasProfile = true; - self.noFocusedWallet = true; - self.isComplete = null; - self.walletName = null; - uxLanguage.update(); - }); - }); - - $rootScope.$on('Local/NewFocusedWallet', function() { - console.log('[index.js.1200:NewFocusedWallet:] TODO'); //TODO - - return; - - - uxLanguage.update(); - self.setFocusedWallet(); - self.updateHistory(); - storageService.getCleanAndScanAddresses(function(err, walletId) { - - 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 { - $rootScope.$emit('Local/NewFocusedWalletReady'); - } - }); - }); - - $rootScope.$on('Local/SetTab', function(event, tab, reset) { - self.setTab(tab, reset); - }); - - $rootScope.$on('disclaimerAccepted', function(event) { - $scope.isDisclaimerAccepted = true; - }); - - $rootScope.$on('Local/WindowResize', function() { - self.physicalScreenWidth = ((window.innerWidth > 0) ? window.innerWidth : screen.width); - }); - - $rootScope.$on('Local/NeedsConfirmation', function(event, txp, cb) { - - function openConfirmationPopup(txp, cb) { - - var config = configService.getSync(); - - $scope.color = config.colorFor[txp.walletId] || '#4A90E2'; - $scope.tx = txFormatService.processTx(txp); - - self.confirmationPopup = $ionicPopup.show({ - templateUrl: 'views/includes/confirm-tx.html', - scope: $scope, - }); - - $scope.processFee = function(amount, fee) { - var walletSettings = configService.getSync().wallet.settings; - var feeAlternativeIsoCode = walletSettings.alternativeIsoCode; - - $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) + '%'; - }; - - $scope.cancel = function() { - return cb(); - }; - - $scope.accept = function() { - return cb(true); - }; - } - - openConfirmationPopup(txp, function(accept) { - self.confirmationPopup.close(); - return cb(accept); - }); - }); - - $rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) { - - function openPasswordPopup(isSetup, cb) { - $scope.data = {}; - $scope.data.password = null; - $scope.isSetup = isSetup; - $scope.isVerification = false; - $scope.loading = false; - var pass = null; - - self.passwordPopup = $ionicPopup.show({ - templateUrl: 'views/includes/password.html', - scope: $scope, - }); - - $scope.cancel = function() { - return cb('No spending password given'); - }; - - $scope.keyPress = function(event) { - if (!$scope.data.password || $scope.loading) return; - if (event.keyCode == 13) $scope.set(); - } - - $scope.set = function() { - $scope.loading = true; - $scope.error = null; - - $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); - }; - }; - - openPasswordPopup(isSetup, function(err, pass) { - self.passwordPopup.close(); - return cb(err, pass); - }); - - }); - - $rootScope.$on('Local/EmailUpdated', function(event, email) { - self.preferences.email = email; - }); - - lodash.each(['NewCopayer', 'CopayerUpdated'], function(eventName) { - $rootScope.$on(eventName, function() { -console.log('[index.js:1324] NewCopayer, CopayerUpdated'); //TODO - return; - // Re try to open wallet (will triggers) - self.setFocusedWallet(); - }); - }); - - $rootScope.$on('Local/NewEncryptionSetting', function() { - var fc = profileService.focusedClient; - self.isPrivKeyEncrypted = fc.isPrivKeyEncrypted(); - $timeout(function() { - $rootScope.$apply(); - }); - }); - - - /* Start setup */ - lodash.assign(self, vanillaScope); - openURLService.init(); -}); diff --git a/old/menu-item.html b/old/menu-item.html deleted file mode 100644 index 68a2d96d9..000000000 --- a/old/menu-item.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - {{ item.title|translate }} - - {{ index.pendingTxProposalsCountForUs }} - - - - diff --git a/old/notifications.html b/old/notifications.html deleted file mode 100644 index 943d9dec7..000000000 --- a/old/notifications.html +++ /dev/null @@ -1,18 +0,0 @@ -
-
-
- - -
-
-

{{noti.title|translate}}

-
{{noti.content|translate}} -
-
{{noti.content|translate}} -
-
-
-
- diff --git a/old/notifications.js b/old/notifications.js deleted file mode 100644 index b87dddb28..000000000 --- a/old/notifications.js +++ /dev/null @@ -1,260 +0,0 @@ -'use strict'; - -angular.module('copayApp.services'). -factory('notification', function($timeout, platformInfo) { - - var isCordova = platformInfo.isCordova; - var notifications = []; - - /* - ls.getItem('notifications', function(err, data) { - if (data) { - notifications = JSON.parse(data); - } - }); - */ - - var queue = []; - var settings = { - info: { - duration: 6000, - enabled: true - }, - funds: { - duration: 7000, - enabled: true - }, - version: { - duration: 60000, - enabled: true - }, - warning: { - duration: 7000, - enabled: true - }, - error: { - duration: 7000, - enabled: true - }, - success: { - duration: 5000, - enabled: true - }, - progress: { - duration: 0, - enabled: true - }, - custom: { - duration: 35000, - enabled: true - }, - details: true, - localStorage: false, - html5Mode: false, - html5DefaultIcon: 'img/favicon.ico' - }; - - function html5Notify(icon, title, content, ondisplay, onclose) { - if (window.webkitNotifications && window.webkitNotifications.checkPermission() === 0) { - if (!icon) { - icon = 'img/favicon.ico'; - } - var noti = window.webkitNotifications.createNotification(icon, title, content); - if (typeof ondisplay === 'function') { - noti.ondisplay = ondisplay; - } - if (typeof onclose === 'function') { - noti.onclose = onclose; - } - noti.show(); - } else { - settings.html5Mode = false; - } - } - - - return { - - /* ========== SETTINGS RELATED METHODS =============*/ - - disableHtml5Mode: function() { - settings.html5Mode = false; - }, - - disableType: function(notificationType) { - settings[notificationType].enabled = false; - }, - - enableHtml5Mode: function() { - // settings.html5Mode = true; - settings.html5Mode = this.requestHtml5ModePermissions(); - }, - - enableType: function(notificationType) { - settings[notificationType].enabled = true; - }, - - getSettings: function() { - return settings; - }, - - toggleType: function(notificationType) { - settings[notificationType].enabled = !settings[notificationType].enabled; - }, - - toggleHtml5Mode: function() { - settings.html5Mode = !settings.html5Mode; - }, - - requestHtml5ModePermissions: function() { - if (window.webkitNotifications) { - if (window.webkitNotifications.checkPermission() === 0) { - return true; - } else { - window.webkitNotifications.requestPermission(function() { - if (window.webkitNotifications.checkPermission() === 0) { - settings.html5Mode = true; - } else { - settings.html5Mode = false; - } - }); - return false; - } - } else { - return false; - } - }, - - - /* ============ QUERYING RELATED METHODS ============*/ - - getAll: function() { - // Returns all notifications that are currently stored - return notifications; - }, - - getQueue: function() { - return queue; - }, - - /* ============== NOTIFICATION METHODS ==============*/ - - info: function(title, content, userData) { - return this.awesomeNotify('info', 'fi-info', title, content, userData); - }, - - funds: function(title, content, userData) { - return this.awesomeNotify('funds', 'icon-receive', title, content, userData); - }, - - version: function(title, content, severe) { - return this.awesomeNotify('version', severe ? 'fi-alert' : 'fi-flag', title, content); - }, - - error: function(title, content, userData) { - return this.awesomeNotify('error', 'fi-x', title, content, userData); - }, - - success: function(title, content, userData) { - return this.awesomeNotify('success', 'fi-check', title, content, userData); - }, - - warning: function(title, content, userData) { - return this.awesomeNotify('warning', 'fi-alert', title, content, userData); - }, - - new: function(title, content, userData) { - return this.awesomeNotify('warning', 'fi-plus', title, content, userData); - }, - - sent: function(title, content, userData) { - return this.awesomeNotify('warning', 'icon-paperplane', title, content, userData); - }, - - awesomeNotify: function(type, icon, title, content, userData) { - /** - * Supposed to wrap the makeNotification method for drawing icons using font-awesome - * rather than an image. - * - * Need to find out how I'm going to make the API take either an image - * resource, or a font-awesome icon and then display either of them. - * Also should probably provide some bits of color, could do the coloring - * through classes. - */ - // image = ''; - return this.makeNotification(type, false, icon, title, content, userData); - }, - - notify: function(image, title, content, userData) { - // Wraps the makeNotification method for displaying notifications with images - // rather than icons - return this.makeNotification('custom', image, true, title, content, userData); - }, - - makeNotification: function(type, image, icon, title, content, userData) { - var notification = { - 'type': type, - 'image': image, - 'icon': icon, - 'title': title, - 'content': content, - 'timestamp': +new Date(), - 'userData': userData - }; - - notifications.push(notification); - - if (settings.html5Mode) { - html5Notify(image, title, content, function() { - // inner on display function - }, function() { - // inner on close function - }); - } - - //this is done because html5Notify() changes the variable settings.html5Mode - if (!settings.html5Mode) { - queue.push(notification); - $timeout(function removeFromQueueTimeout() { - queue.splice(queue.indexOf(notification), 1); - }, settings[type].duration); - } - - // Mobile notification - if (window && window.navigator && window.navigator.vibrate) { - window.navigator.vibrate([200, 100, 200]); - }; - - if (document.hidden && (type == 'info' || type == 'funds') && !isCordova) { - new window.Notification(title, { - body: content, - icon: 'img/notification.png' - }); - } - - this.save(); - return notification; - }, - - - /* ============ PERSISTENCE METHODS ============ */ - - save: function() { - // Save all the notifications into localStorage - if (settings.localStorage) { - localStorage.setItem('notifications', JSON.stringify(notifications)); - } - }, - - restore: function() { - // Load all notifications from localStorage - }, - - clear: function() { - notifications = []; - this.save(); - } - - }; - } -); diff --git a/old/notificationsService.js b/old/notificationsService.js deleted file mode 100644 index d71bea4ee..000000000 --- a/old/notificationsService.js +++ /dev/null @@ -1,115 +0,0 @@ -'use strict'; -angular.module('copayApp.services') - .factory('notificationService', function profileServiceFactory($filter, notification, lodash, configService, gettext) { - - var root = {}; - - var groupingTime = 5000; - var lastNotificationOnWallet = {}; - - root.getLast = function(walletId) { - var last = lastNotificationOnWallet[walletId]; - if (!last) return null; - - return Date.now() - last.ts < groupingTime ? last : null; - }; - - root.storeLast = function(notificationData, walletId) { - - if (notificationData.type == 'NewAddress') - return; - - lastNotificationOnWallet[walletId] = { - creatorId: notificationData.creatorId, - type: notificationData.type, - ts: Date.now(), - }; - }; - - root.shouldSkip = function(notificationData, last) { - if (!last) return false; - - // rules... - if (last.type === 'NewTxProposal' && - notificationData.type === 'TxProposalAcceptedBy') - return true; - - if (last.type === 'TxProposalFinallyAccepted' && - notificationData.type === 'NewOutgoingTx') - return true; - - if (last.type === 'TxProposalRejectedBy' && - notificationData.type === 'TxProposalFinallyRejected') - return true; - - return false; - }; - - - root.newBWCNotification = function(notificationData, walletId, walletName) { - var last = root.getLast(walletId); - root.storeLast(notificationData, walletId); - - if (root.shouldSkip(notificationData, last)) - return; - - var config = configService.getSync(); - config.colorFor = config.colorFor || {}; - var color = config.colorFor[walletId] || '#4A90E2'; - var name = config.aliasFor[walletId] || walletName; - - switch (notificationData.type) { - case 'NewTxProposal': - notification.new(gettext('New Payment Proposal'), - name, { - color: color - }); - break; - case 'TxProposalAcceptedBy': - notification.success(gettext('Payment Proposal Signed by Copayer'), - name, { - color: color - }); - break; - case 'TxProposalRejectedBy': - notification.error(gettext('Payment Proposal Rejected by Copayer'), - name, { - color: color - }); - break; - case 'TxProposalFinallyRejected': - notification.error(gettext('Payment Proposal Rejected'), - name, { - color: color - }); - break; - case 'NewOutgoingTx': - notification.sent(gettext('Payment Sent'), - name, { - color: color - }); - break; - case 'NewIncomingTx': - notification.funds(gettext('Funds received'), - name, { - color: color - }); - break; - case 'ScanFinished': - notification.success(gettext('Scan Finished'), - name, { - color: color - }); - break; - - case 'NewCopayer': - // No UX notification - break; - case 'BalanceUpdated': - // No UX notification - break; - } - }; - - return root; - }); diff --git a/old/preferencesGlobal.html b/old/preferencesGlobal.html deleted file mode 100644 index 35af966ad..000000000 --- a/old/preferencesGlobal.html +++ /dev/null @@ -1,86 +0,0 @@ - -
-
- -
-

- -

- - -

- - - - - Use Unconfirmed Funds - - -
-

- - Enable push notifications - -
- -
-
Push notifications for Copay are currently disabled. Enable them in the Settings app.
- -
- -

- - - Enable Glidera Service - -

- - - Enable Coinbase Service - -

- - -

-
-
diff --git a/old/preferencesGlobal.js b/old/preferencesGlobal.js deleted file mode 100644 index dbedb3389..000000000 --- a/old/preferencesGlobal.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -angular.module('copayApp.controllers').controller('preferencesGlobalController', - function($scope, $rootScope, $log, configService, uxLanguage, platformInfo, pushNotificationsService, profileService, feeService) { - - $scope.init = function() { - var config = configService.getSync(); - var isCordova = platformInfo.isCordova; - - if (isCordova && StatusBar.isVisible) { - StatusBar.backgroundColorByHexString("#4B6178"); - } - - $scope.unitName = config.wallet.settings.unitName; - $scope.currentLanguageName = uxLanguage.getCurrentLanguageName(); - $scope.selectedAlternative = { - name: config.wallet.settings.alternativeName, - isoCode: config.wallet.settings.alternativeIsoCode - }; - $scope.feeOpts = feeService.feeOpts; - $scope.currentFeeLevel = feeService.getCurrentFeeLevel(); - $scope.usePushNotifications = isCordova && !platformInfo.isWP; - $scope.PNEnabledByUser = true; - $scope.isIOSApp = platformInfo.isIOS && isCordova; - if ($scope.isIOSApp) { - cordova.plugins.diagnostic.isRemoteNotificationsEnabled(function(isEnabled) { - $scope.PNEnabledByUser = isEnabled; - $scope.$digest(); - }); - } - $scope.spendUnconfirmed = config.wallet.spendUnconfirmed; - $scope.glideraEnabled = config.glidera.enabled; - $scope.coinbaseEnabled = config.coinbase.enabled; - $scope.pushNotifications = config.pushNotifications.enabled; - }; - - $scope.openSettings = function() { - cordova.plugins.diagnostic.switchToSettings(function() { - $log.debug('switched to settings'); - }, function(err) { - $log.debug(err); - }); - } - - $scope.spendUnconfirmedChange = function() { - var opts = { - wallet: { - spendUnconfirmed: $scope.spendUnconfirmed - } - }; - configService.set(opts, function(err) { - if (err) $log.debug(err); - }); - }; - - $scope.pushNotificationsChange = function() { - var opts = { - pushNotifications: { - enabled: $scope.pushNotifications - } - }; - configService.set(opts, function(err) { - if (opts.pushNotifications.enabled) - pushNotificationsService.enableNotifications(profileService.walletClients); - else - pushNotificationsService.disableNotifications(profileService.walletClients); - if (err) $log.debug(err); - }); - }; - - $scope.glideraChange = function() { - var opts = { - glidera: { - enabled: $scope.glideraEnabled - } - }; - configService.set(opts, function(err) { - $rootScope.$emit('Local/GlideraUpdated'); - if (err) $log.debug(err); - }); - }; - - $scope.coinbaseChange = function() { - var opts = { - coinbase: { - enabled: $scope.coinbaseEnabled - } - }; - configService.set(opts, function(err) { - $rootScope.$emit('Local/CoinbaseUpdated'); - if (err) $log.debug(err); - }); - }; - }); diff --git a/old/sidebar.html b/old/sidebar.html deleted file mode 100644 index 9345ac9d0..000000000 --- a/old/sidebar.html +++ /dev/null @@ -1,57 +0,0 @@ - diff --git a/old/tab-scan.js b/old/tab-scan.js deleted file mode 100644 index 423fc30d9..000000000 --- a/old/tab-scan.js +++ /dev/null @@ -1,194 +0,0 @@ -'use strict'; - -angular.module('copayApp.controllers').controller('tabScanController', function($scope, $timeout, $ionicModal, $log, $ionicPopup, configService, gettextCatalog, platformInfo, bitcore, lodash, $state, incomingData) { - - var isCordova = platformInfo.isCordova; - var isWP = platformInfo.isWP; - var isIOS = platformInfo.isIOS; - - - - var _showAlert = function(title, msg, cb) { - $log.warn(title + ":"+ msg); - var alertPopup = $ionicPopup.alert({ - title: title, - template: msg - }); - - if (!cb) cb = function(res) {}; - - alertPopup.then(cb); - }; - - var _dataScanned = function(data) { - $log.debug('Scanned:' + data); - if (!incomingData.redir(data)) { - $log.warn('Fail to process scanned data'); - _showAlert('Bad bitcoin address', 'Could not recognize the bitcoin address', function(res) { - $scope.init(); - }); - } - }; - - var onSuccess = function(result) { - $timeout(function() { - window.plugins.spinnerDialog.hide(); - }, 100); - if (isWP && result.cancelled) return; - - $timeout(function() { - var data = isIOS ? result : result.text; - // Check if the current page is tabs.scan - if ($state.is('tabs.scan')) { - _dataScanned(data); - return; - } - }, 1000); - }; - - var onError = function(error) { - $timeout(function() { - window.plugins.spinnerDialog.hide(); - }, 100); - }; - - $scope.cordovaOpenScanner = function() { - window.plugins.spinnerDialog.show(null, gettextCatalog.getString('Preparing camera...'), true); - $timeout(function() { - if (isIOS) { - cloudSky.zBar.scan({}, onSuccess, onError); - } else { - cordova.plugins.barcodeScanner.scan(onSuccess, onError); - } - if ($scope.beforeScan) { - $scope.beforeScan(); - } - }, 100); - }; - - $scope.modalOpenScanner = function() { - $ionicModal.fromTemplateUrl('views/modals/scanner.html', { - scope: $scope, - animation: 'slide-in-up' - }).then(function(modal) { - $scope.scannerModal = modal; - $scope.scannerModal.show(); - }); - }; - - $scope.openScanner = function() { - if (isCordova) { - $scope.cordovaOpenScanner(); - } else { - $scope.modalOpenScanner(); - } - }; - - // QR code Scanner - var video; - var canvas; - var $video; - var context; - var localMediaStream; - var prevResult; - var scanTimer; - - var _scan = function(evt) { - if (localMediaStream) { - context.drawImage(video, 0, 0, 300, 225); - try { - qrcode.decode(); - } catch (e) { - //qrcodeError(e); - } - } - scanTimer = $timeout(_scan, 800); - }; - - var _scanStop = function() { - $timeout.cancel(scanTimer); - if (localMediaStream && localMediaStream.active) { - var localMediaStreamTrack = localMediaStream.getTracks(); - for (var i = 0; i < localMediaStreamTrack.length; i++) { - localMediaStreamTrack[i].stop(); - } - } else { - try { - localMediaStream.stop(); - } catch (e) { - // Older Chromium not support the STOP function - }; - } - localMediaStream = null; - if (video && video.src) video.src = ''; - }; - - qrcode.callback = function(data) { - if (prevResult != data) { - prevResult = data; - return; - } - // Check if the current page is tabs.scan - _scanStop(); - if ($state.is('tabs.scan')) { - _dataScanned(data); - return; - } - $scope.cancel(); - }; - - var _successCallback = function(stream) { - video.src = (window.URL && window.URL.createObjectURL(stream)) || stream; - localMediaStream = stream; - video.play(); - $timeout(_scan, 1000); - }; - - var _videoError = function(err) { - $scope.cancel(); - }; - - var setScanner = function() { - navigator.getUserMedia = navigator.getUserMedia || - navigator.webkitGetUserMedia || navigator.mozGetUserMedia || - navigator.msGetUserMedia; - window.URL = window.URL || window.webkitURL || - window.mozURL || window.msURL; - }; - - $scope.init = function() { - if (isCordova) { - $scope.cordovaOpenScanner(); - return; - } - setScanner(); - $timeout(function() { - if ($scope.beforeScan) { - $scope.beforeScan(); - } - canvas = document.getElementById('qr-canvas'); - context = canvas.getContext('2d'); - - video = document.getElementById('qrcode-scanner-video'); - $video = angular.element(video); - canvas.width = 300; - canvas.height = 225; - context.clearRect(0, 0, 300, 225); - - navigator.getUserMedia({ - video: true - }, _successCallback, _videoError); - }, 500); - }; - - $scope.cancel = function() { - _scanStop(); - $scope.scannerModal.hide(); - $scope.scannerModal.remove(); - }; - - $scope.$on("$destroy", function(){ - _scanStop(); - }); - -}); diff --git a/old/topbar.html b/old/topbar.html deleted file mode 100644 index e47b1c061..000000000 --- a/old/topbar.html +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/old/topbar.js b/old/topbar.js deleted file mode 100644 index b3f58ad0e..000000000 --- a/old/topbar.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -angular.module('copayApp.controllers').controller('topbarController', function(go) { - - this.goHome = function() { - go.walletHome(); - }; - - this.goPreferences = function() { - go.preferences(); - }; - -}); diff --git a/old/uri.html b/old/uri.html deleted file mode 100644 index 212aaf41e..000000000 --- a/old/uri.html +++ /dev/null @@ -1,11 +0,0 @@ - -
-
- -
-
-

- Please wait to be redirected... -

-
- diff --git a/old/uri.js b/old/uri.js deleted file mode 100644 index 5a54eb254..000000000 --- a/old/uri.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; -angular.module('copayApp.controllers').controller('uriController', - function($stateParams, $log, openURLService) { - - - /* This is only for BROWSER links, it is not excecuted on mobile devices */ - - $log.info('DEEP LINK from Browser:' + $stateParams.url); - openURLService.handleURL({ - url: $stateParams.url - }); - }); diff --git a/old/walletHome.html b/old/walletHome.html deleted file mode 100644 index 91e2c217e..000000000 --- a/old/walletHome.html +++ /dev/null @@ -1,534 +0,0 @@ - -
-
- -
-
-
- You do not have any wallet -
- -
- -
-
-
-
-
-
-
-
-
- Updating Wallet... -
-
- -
- - - -
- - - -
-
-
-
- {{index.updateError|translate}} - -
- -
- Scan status finished with error -
Tap to retry -
- -
- {{index.totalBalanceStr}} -
{{index.totalBalanceAlternative}} {{index.alternativeIsoCode}}
-
- Pending Confirmation: {{index.pendingAmountStr}} -
-
- -
- [Balance Hidden] -
- Tap and hold to show -
-
-
-
-
- ... -
-
-
- -
- -
-
- -
-
- -
-
-
- - - WARNING: Key derivation is not working on this device/wallet. Actions cannot be performed on this wallet. - -
-
-
-
- - - WARNING: Wallet not registered - -
-
- This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information. -
-
- - Recreate - -
-
- -
- {{newRelease}} -
- -
-

Payment Proposals

-

Unsent transactions

-
-
-
- -
- Total Locked Balance: - {{index.lockedBalanceStr}} - {{index.lockedBalanceAlternative}} - {{index.alternativeIsoCode}} -
-
- - - -

- Activity - -

- -
No transactions yet -
- -
- -
-
-
- -
-
-
{{index.txProgress}} transactions downloaded
-
Updating transaction history. Please stand by.
-
-
-
- -
-
-
- -
-
-   -
-
-   -
-
-
- -
-
-
- sync - sync - sync -
-
- - - {{btx.note.body}} - Received - - - - - {{btx.message}} - {{btx.note.body}} - {{index.addressbook[btx.addressTo]}} - Sent - - - - - {{btx.note.body}} - Moved - - - - Invalid -
-
- -
- - + - - - - (possible double spend) - - - {{btx.amountStr}} - - -
- - - Unconfirmed - -
-
-
- -
-
- -
-
- -
-
- - - -
-
- -
-
-
- - -
- -
-
- -
-
Backup Needed
-

- Before receiving funds, you must backup your wallet. If this device is lost, it is impossible to access your funds without a backup. -

- -
-
-
- - {{home.addrError|translate}} - -
-
- -
-

My Bitcoin address

-
- -
-
- -
-
-
-

- {{home.generatingAddress ? '...' : home.addr}} -

-
-
-
-
-
-
- -
-
- -
-
-
-
-
- Share this wallet address to receive payments. To protect your privacy, new addresses are generated automatically once you use them. - Generate new address -
-
- Share this wallet address to receive payments. -
-
-
-
-
-
- - - -
-
-

- - Send Max - Send Max - -
- Payment expires - -
-

-
- -
-
-
- - {{home.error|translate}} - -
-
-
-
- -
-
- - - - - Not valid - - - - - -
- -
- -
- {{index.addressbook[_address] || _address}} -
- - - -
-
-
-
- - - -
- - - -
-
-
- -
-
-
- - - Not valid - - - - -
-
- - -
-
-
-
-
- -
- -
-
-
- -
-
- Cancel -
-
- -
- -
-
-
-
-
-
- -
-
- -
-
-
-
-
- -
-
diff --git a/old/walletHome.js b/old/walletHome.js deleted file mode 100644 index 2cbd4d59d..000000000 --- a/old/walletHome.js +++ /dev/null @@ -1,944 +0,0 @@ -'use strict'; - -angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, notification, txStatus, profileService, lodash, configService, rateService, storageService, bitcore, gettext, gettextCatalog, platformInfo, addressService, ledger, bwcError, confirmDialog, txFormatService, addressbookService, go, feeService, walletService, fingerprintService, nodeWebkit, ongoingProcess) { - - var isCordova = platformInfo.isCordova; - var isWP = platformInfo.isWP; - var isAndroid = platformInfo.isAndroid; - var isChromeApp = platformInfo.isChromeApp; - - var self = this; - $rootScope.shouldHideMenuBar = false; - $rootScope.wpInputFocused = false; - var config = configService.getSync(); - var configWallet = config.wallet; - var walletSettings = configWallet.settings; - var ret = {}; - - // INIT. Global value - ret.unitToSatoshi = walletSettings.unitToSatoshi; - ret.satToUnit = 1 / ret.unitToSatoshi; - ret.unitName = walletSettings.unitName; - ret.alternativeIsoCode = walletSettings.alternativeIsoCode; - ret.alternativeName = walletSettings.alternativeName; - ret.alternativeAmount = 0; - ret.unitDecimals = walletSettings.unitDecimals; - ret.isCordova = isCordova; - ret.addresses = []; - ret.isMobile = platformInfo.isMobile; - ret.isWindowsPhoneApp = platformInfo.isWP; - ret.countDown = null; - ret.sendMaxInfo = {}; - ret.showAlternative = false; - ret.fromInputAmount = null; - var vanillaScope = ret; - - var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) { - if (!data) return; - - self.setForm(data); - $rootScope.$emit('Local/SetTab', 'send'); - var form = $scope.sendForm; - if (form.address.$invalid && !ongoingProcess.get('fetchingPayPro')) { - self.resetForm(); - self.error = gettext('Could not recognize a valid Bitcoin QR Code'); - } - }); - - var disablePaymentUriListener = $rootScope.$on('paymentUri', function(event, uri) { - $rootScope.$emit('Local/SetTab', 'send'); - $timeout(function() { - self.setForm(uri); - }, 100); - }); - - var disableAddrListener = $rootScope.$on('Local/AddressIsUsed', function() { - self.setAddress(true); - }); - - var disableFocusListener = $rootScope.$on('Local/NewFocusedWalletReady', function() { - self.addr = null; - self.resetForm(); - $scope.search = ''; - - if (profileService.focusedClient && profileService.focusedClient.isComplete()) { - self.setAddress(); - self.setSendFormInputs(); - } - - $log.debug('Cleaning WalletHome Instance'); - lodash.each(self, function(v, k) { - if (lodash.isFunction(v)) return; - if (!lodash.isUndefined(vanillaScope[k])) { - self[k] = vanillaScope[k]; - return; - } - if (k == 'isRateAvailable') return; - - delete self[k]; - }); - }); - - var disableResumeListener = $rootScope.$on('Local/Resume', function() { - // This is needed then the apps go to sleep - self.bindTouchDown(); - }); - - var disableTabListener = $rootScope.$on('Local/TabChanged', function(e, tab) { - // This will slow down switch, do not add things here! - switch (tab) { - case 'receive': - // just to be sure we have an address - self.setAddress(); - break; - case 'send': - self.resetError(); - }; - }); - - $scope.$on('$destroy', function() { - disableAddrListener(); - disableScannerListener(); - disablePaymentUriListener(); - disableTabListener(); - disableFocusListener(); - disableResumeListener(); - $rootScope.shouldHideMenuBar = false; - }); - - if (isCordova && StatusBar.isVisible) { - var backgroundColor = profileService.focusedClient ? profileService.focusedClient.backgroundColor : "#4B6178"; - StatusBar.backgroundColorByHexString(backgroundColor); - } - - this.onQrCodeScanned = function(data) { - if (data) go.send(); - $rootScope.$emit('dataScanned', data); - }; - - rateService.whenAvailable(function() { - self.isRateAvailable = true; - $rootScope.$digest(); - }); - - var getClipboard = function(cb) { - if (!isCordova || platformInfo.isWP) return cb(); - - window.cordova.plugins.clipboard.paste(function(value) { - var fc = profileService.focusedClient; - var Address = bitcore.Address; - var networkName = fc.credentials.network; - if (Address.isValid(value, networkName) && !$scope.newAddress) { - return cb(value); - } - }); - }; - - var handleEncryptedWallet = function(client, cb) { - if (!walletService.isEncrypted(client)) return cb(); - $rootScope.$emit('Local/NeedsPassword', false, function(err, password) { - if (err) return cb(err); - return cb(walletService.unlock(client, password)); - }); - }; - - var accept_msg = gettextCatalog.getString('Accept'); - var cancel_msg = gettextCatalog.getString('Cancel'); - var confirm_msg = gettextCatalog.getString('Confirm'); - - this.openAddressbookModal = function(wallets, address) { - $scope.wallets = wallets; - $scope.address = address; - $scope.self = self; - - $ionicModal.fromTemplateUrl('views/modals/addressbook.html', { - scope: $scope - }).then(function(modal) { - $scope.addressbookModal = modal; - $scope.addressbookModal.show(); - }); - }; - - var GLIDERA_LOCK_TIME = 6 * 60 * 60; - // isGlidera flag is a security measure so glidera status is not - // only determined by the tx.message - this.openTxpModal = function(tx, copayers, isGlidera) { - $scope.self = self; - $scope.tx = tx; - $scope.copayers = copayers; - $scope.isGlidera = isGlidera; - $scope.error = null; - $scope.loading = null; - $scope.paymentExpired = null; - $scope.currentSpendUnconfirmed = configWallet.spendUnconfirmed; - - $ionicModal.fromTemplateUrl('views/modals/txp-details.html', { - scope: $scope - }).then(function(modal) { - $scope.txpDetailsModal = modal; - $scope.txpDetailsModal.show(); - }); - }; - - this.setAddress = function(forceNew) { - self.addrError = null; - var client = profileService.focusedClient; - if (!client || !client.isComplete()) return; - - // Address already set? - if (!forceNew && self.addr) { - return; - } - - self.generatingAddress = true; - $timeout(function() { - addressService.getAddress(client.credentials.walletId, forceNew, function(err, addr) { - self.generatingAddress = false; - - if (err) { - self.addrError = err; - } else { - if (addr) - self.addr = addr; - } - - $scope.$digest(); - }); - }); - }; - - this.copyToClipboard = function(addr, $event) { - - var showPopover = function() { - - $ionicPopover.fromTemplateUrl('views/includes/copyToClipboard.html', { - scope: $scope - }).then(function(popover) { - $scope.popover = popover; - $scope.popover.show($event); - }); - - $scope.close = function() { - $scope.popover.hide(); - } - - $timeout(function() { - $scope.popover.hide(); //close the popover after 0.7 seconds - }, 700); - - $scope.$on('$destroy', function() { - $scope.popover.remove(); - }); - }; - - if (isCordova) { - window.cordova.plugins.clipboard.copy(addr); - window.plugins.toast.showShortCenter(gettextCatalog.getString('Copied to clipboard')); - } else if (platformInfo.isNW) { - nodeWebkit.writeToClipboard(addr); - showPopover($event); - } - }; - - this.shareAddress = function(addr) { - if (isCordova) { - window.plugins.socialsharing.share('bitcoin:' + addr, null, null, null); - } - }; - - // Send - - this.resetError = function() { - this.error = this.success = null; - }; - - this.bindTouchDown = function(tries) { - var self = this; - tries = tries || 0; - if (tries > 5) return; - var e = document.getElementById('menu-walletHome'); - if (!e) return $timeout(function() { - self.bindTouchDown(++tries); - }, 500); - - // on touchdown elements - $log.debug('Binding touchstart elements...'); - ['hamburger', 'menu-walletHome', 'menu-send', 'menu-receive'].forEach(function(id) { - var e = document.getElementById(id); - if (e) e.addEventListener('touchstart', function() { - try { - event.preventDefault(); - } catch (e) {}; - angular.element(e).triggerHandler('click'); - }, true); - }); - } - - this.hideMenuBar = lodash.debounce(function(hide) { - if (hide) { - $rootScope.shouldHideMenuBar = true; - } else { - $rootScope.shouldHideMenuBar = false; - } - $rootScope.$digest(); - }, 100); - - this.formFocus = function(what) { - if (isCordova && this.isWindowsPhoneApp) { - this.hideMenuBar(what); - } - var self = this; - if (isCordova && !this.isWindowsPhoneApp && what == 'address') { - getClipboard(function(value) { - if (value) { - document.getElementById("amount").focus(); - $timeout(function() { - window.plugins.toast.showShortCenter(gettextCatalog.getString('Pasted from clipboard')); - self.setForm(value); - }, 100); - } - }); - } - }; - - this.setSendFormInputs = function() { - var unitToSat = this.unitToSatoshi; - var satToUnit = 1 / unitToSat; - /** - * Setting the two related amounts as properties prevents an infinite - * recursion for watches while preserving the original angular updates - * - */ - Object.defineProperty($scope, - "_alternative", { - get: function() { - return $scope.__alternative; - }, - set: function(newValue) { - $scope.__alternative = newValue; - if (self.isRateAvailable) { - $scope._amount = parseFloat((rateService.fromFiat(newValue, self.alternativeIsoCode) * satToUnit).toFixed(self.unitDecimals), 10); - } else { - $scope.__amount = null; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty($scope, - "_amount", { - get: function() { - return $scope.__amount; - }, - set: function(newValue) { - $scope.__amount = newValue; - if (self.isRateAvailable) { - $scope.__alternative = parseFloat((rateService.toFiat(newValue * self.unitToSatoshi, self.alternativeIsoCode)).toFixed(2), 10); - } else { - $scope.__alternative = null; - } - self.alternativeAmount = $scope.__alternative; - self.resetError(); - }, - enumerable: true, - configurable: true - }); - - Object.defineProperty($scope, - "_address", { - get: function() { - return $scope.__address; - }, - set: function(newValue) { - $scope.__address = self.onAddressChange(newValue); - if ($scope.sendForm && $scope.sendForm.address.$valid) { - self.lockAddress = true; - } - }, - enumerable: true, - configurable: true - }); - - var fc = profileService.focusedClient; - // ToDo: use a credential's (or fc's) function for this - this.hideNote = !fc.credentials.sharedEncryptingKey; - }; - - this.setSendError = function(err) { - var fc = profileService.focusedClient; - var prefix = - fc.credentials.m > 1 ? gettextCatalog.getString('Could not create payment proposal') : gettextCatalog.getString('Could not send payment'); - - this.error = bwcError.msg(err, prefix); - - $timeout(function() { - $scope.$digest(); - }, 1); - }; - - this.setAmount = function(amount, useAlternativeAmount) { - $scope.showAlternative = useAlternativeAmount; - - self.fromInputAmount = true; - self.setForm(null, amount, null); - }; - - this.submitForm = function() { - if (!$scope._amount || !$scope._address) return; - var client = profileService.focusedClient; - var unitToSat = this.unitToSatoshi; - var currentSpendUnconfirmed = configWallet.spendUnconfirmed; - - var outputs = []; - - this.resetError(); - - if (isCordova && this.isWindowsPhoneApp) - $rootScope.shouldHideMenuBar = true; - - var form = $scope.sendForm; - var comment = form.comment.$modelValue; - - // ToDo: use a credential's (or fc's) function for this - if (comment && !client.credentials.sharedEncryptingKey) { - var msg = 'Could not add message to imported wallet without shared encrypting key'; - $log.warn(msg); - return self.setSendError(gettext(msg)); - } - - if (form.amount.$modelValue * unitToSat > Number.MAX_SAFE_INTEGER) { - var msg = 'Amount too big'; - $log.warn(msg); - return self.setSendError(gettext(msg)); - }; - - $timeout(function() { - var paypro = self._paypro; - var address, amount; - - address = form.address.$modelValue; - amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0)); - - outputs.push({ - 'toAddress': address, - 'amount': amount, - 'message': comment - }); - - var txp = {}; - - if (!lodash.isEmpty(self.sendMaxInfo)) { - txp.sendMax = true; - txp.inputs = self.sendMaxInfo.inputs; - txp.fee = self.sendMaxInfo.fee; - } else { - txp.amount = amount; - } - - txp.toAddress = address; - txp.outputs = outputs; - txp.message = comment; - txp.payProUrl = paypro ? paypro.url : null; - txp.excludeUnconfirmedUtxos = configWallet.spendUnconfirmed ? false : true; - txp.feeLevel = walletSettings.feeLevel || 'normal'; - - ongoingProcess.set('creatingTx', true); - walletService.createTx(client, txp, function(err, createdTxp) { - ongoingProcess.set('creatingTx', false); - if (err) { - return self.setSendError(err); - } - - if (!client.canSign() && !client.isPrivKeyExternal()) { - $log.info('No signing proposal: No private key'); - ongoingProcess.set('sendingTx', true); - walletService.publishTx(client, createdTxp, function(err, publishedTxp) { - ongoingProcess.set('sendingTx', false); - if (err) { - return self.setSendError(err); - } - self.resetForm(); - go.walletHome(); - var type = txStatus.notify(createdTxp); - $scope.openStatusModal(type, createdTxp, function() { - return $scope.$emit('Local/TxProposalAction'); - }); - }); - } else { - $rootScope.$emit('Local/NeedsConfirmation', createdTxp, function(accept) { - if (accept) self.confirmTx(createdTxp); - else self.resetForm(); - }); - } - }); - - }, 100); - }; - - this.confirmTx = function(txp) { - var client = profileService.focusedClient; - var self = this; - - fingerprintService.check(client, function(err) { - if (err) { - return self.setSendError(err); - } - - handleEncryptedWallet(client, function(err) { - if (err) { - return self.setSendError(err); - } - - ongoingProcess.set('sendingTx', true); - walletService.publishTx(client, txp, function(err, publishedTxp) { - ongoingProcess.set('sendingTx', false); - if (err) { - return self.setSendError(err); - } - - ongoingProcess.set('signingTx', true); - walletService.signTx(client, publishedTxp, function(err, signedTxp) { - ongoingProcess.set('signingTx', false); - walletService.lock(client); - if (err) { - $scope.$emit('Local/TxProposalAction'); - return self.setSendError( - err.message ? - err.message : - gettext('The payment was created but could not be completed. Please try again from home screen')); - } - - if (signedTxp.status == 'accepted') { - ongoingProcess.set('broadcastingTx', true); - walletService.broadcastTx(client, signedTxp, function(err, broadcastedTxp) { - ongoingProcess.set('broadcastingTx', false); - if (err) { - return self.setSendError(err); - } - self.resetForm(); - go.walletHome(); - var type = txStatus.notify(broadcastedTxp); - $scope.openStatusModal(type, broadcastedTxp, function() { - $scope.$emit('Local/TxProposalAction', broadcastedTxp.status == 'broadcasted'); - }); - }); - } else { - self.resetForm(); - go.walletHome(); - var type = txStatus.notify(signedTxp); - $scope.openStatusModal(type, signedTxp, function() { - $scope.$emit('Local/TxProposalAction'); - }); - } - }); - }); - }); - }); - }; - - $scope.openStatusModal = function(type, txp, cb) { - var fc = profileService.focusedClient; - $scope.type = type; - $scope.tx = txFormatService.processTx(txp); - $scope.color = fc.backgroundColor; - $scope.cb = cb; - - $ionicModal.fromTemplateUrl('views/modals/tx-status.html', { - scope: $scope, - animation: 'slide-in-up' - }).then(function(modal) { - $scope.txStatusModal = modal; - $scope.txStatusModal.show(); - }); - }; - - $scope.openSearchModal = function() { - var fc = profileService.focusedClient; - $scope.color = fc.backgroundColor; - $scope.self = self; - - $ionicModal.fromTemplateUrl('views/modals/search.html', { - scope: $scope, - focusFirstInput: true - }).then(function(modal) { - $scope.searchModal = modal; - $scope.searchModal.show(); - }); - }; - - $scope.openCustomInputAmountModal = function(addr) { - var fc = profileService.focusedClient; - $scope.color = fc.backgroundColor; - $scope.self = self; - $scope.addr = addr; - - $ionicModal.fromTemplateUrl('views/modals/customAmount.html', { - scope: $scope - }).then(function(modal) { - $scope.customAmountModal = modal; - $scope.customAmountModal.show(); - }); - }; - - $scope.openAmountModal = function(addr) { - if (isCordova) - $scope.openInputAmountModal(addr); - else - $scope.openCustomInputAmountModal(addr); - }; - - $scope.openInputAmountModal = function(addr) { - var fc = profileService.focusedClient; - $scope.color = fc.backgroundColor; - $scope.showAlternativeAmount = $scope.showAlternative || null; - if ($scope.showAlternativeAmount) { - $scope.amount = $scope.sendForm.alternative.$viewValue || null; - } else { - $scope.amount = $scope.sendForm.amount.$viewValue || null; - } - $scope.self = self; - $scope.addr = addr; - - $ionicModal.fromTemplateUrl('views/modals/inputAmount.html', { - scope: $scope - }).then(function(modal) { - $scope.inputAmountModal = modal; - $scope.inputAmountModal.show(); - }); - }; - - this.setForm = function(to, amount, comment) { - var form = $scope.sendForm; - if (to) { - form.address.$setViewValue(to); - form.address.$isValid = true; - form.address.$render(); - this.lockAddress = true; - } - - if (amount) { - form.amount.$setViewValue("" + amount); - form.amount.$isValid = true; - form.amount.$render(); - if (!this.fromInputAmount) - this.lockAmount = true; - this.fromInputAmount = false; - } - - if (comment) { - form.comment.$setViewValue(comment); - form.comment.$isValid = true; - form.comment.$render(); - } - }; - - this.resetForm = function() { - this.resetError(); - this.sendMaxInfo = {}; - if (this.countDown) $interval.cancel(this.countDown); - this._paypro = null; - - this.lockAddress = false; - this.lockAmount = false; - - this._amount = this._address = null; - - var form = $scope.sendForm; - - if (form && form.amount) { - form.amount.$pristine = true; - form.amount.$setViewValue(''); - form.amount.$render(); - - form.comment.$setViewValue(''); - form.comment.$render(); - form.$setPristine(); - - if (form.address) { - form.address.$pristine = true; - form.address.$setViewValue(''); - form.address.$render(); - } - } - $timeout(function() { - $rootScope.$digest(); - }, 1); - }; - - this.setFromPayPro = function(uri, cb) { - if (!cb) cb = function() {}; - - var fc = profileService.focusedClient; - if (isChromeApp) { - this.error = gettext('Payment Protocol not supported on Chrome App'); - return cb(true); - } - - var satToUnit = 1 / this.unitToSatoshi; - var self = this; - /// Get information of payment if using Payment Protocol - ongoingProcess.set('fetchingPayPro', true); - - $log.debug('Fetch PayPro Request...', uri); - $timeout(function() { - fc.fetchPayPro({ - payProUrl: uri, - }, function(err, paypro) { - ongoingProcess.set('fetchingPayPro', false); - - if (err) { - $log.warn('Could not fetch payment request:', err); - self.resetForm(); - var msg = err.toString(); - if (msg.match('HTTP')) { - msg = gettext('Could not fetch payment information'); - } - self.error = msg; - $timeout(function() { - $rootScope.$digest(); - }, 1); - return cb(true); - } - - if (!paypro.verified) { - self.resetForm(); - $log.warn('Failed to verify payment protocol signatures'); - self.error = gettext('Payment Protocol Invalid'); - $timeout(function() { - $rootScope.$digest(); - }, 1); - return cb(true); - } - - self._paypro = paypro; - self.setForm(paypro.toAddress, (paypro.amount * satToUnit).toFixed(self.unitDecimals), paypro.memo); - _paymentTimeControl(paypro.expires); - return cb(); - }); - }, 1); - }; - - function _paymentTimeControl(expirationTime) { - self.paymentExpired = false; - setExpirationTime(); - - self.countDown = $interval(function() { - setExpirationTime(); - }, 1000); - - function setExpirationTime() { - var now = Math.floor(Date.now() / 1000); - if (now > expirationTime) { - setExpiredValues(); - return; - } - - var totalSecs = expirationTime - now; - var m = Math.floor(totalSecs / 60); - var s = totalSecs % 60; - self.remainingTimeStr = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2); - }; - - function setExpiredValues() { - self.paymentExpired = true; - self.remainingTimeStr = null; - self._paypro = null; - self.error = gettext('Cannot sign: The payment request has expired'); - if (self.countDown) $interval.cancel(self.countDown); - }; - }; - - this.setFromUri = function(uri) { - var self = this; - - function sanitizeUri(uri) { - // Fixes when a region uses comma to separate decimals - var regex = /[\?\&]amount=(\d+([\,\.]\d+)?)/i; - var match = regex.exec(uri); - if (!match || match.length === 0) { - return uri; - } - var value = match[0].replace(',', '.'); - var newUri = uri.replace(regex, value); - return newUri; - }; - - var satToUnit = 1 / this.unitToSatoshi; - - // URI extensions for Payment Protocol with non-backwards-compatible request - if ((/^bitcoin:\?r=[\w+]/).exec(uri)) { - uri = decodeURIComponent(uri.replace('bitcoin:?r=', '')); - this.setFromPayPro(uri, function(err) { - if (err) { - return err; - } - }); - } else { - uri = sanitizeUri(uri); - - if (!bitcore.URI.isValid(uri)) { - return uri; - } - var parsed = new bitcore.URI(uri); - - var addr = parsed.address ? parsed.address.toString() : ''; - var message = parsed.message; - - var amount = parsed.amount ? - (parsed.amount.toFixed(0) * satToUnit).toFixed(this.unitDecimals) : 0; - - - if (parsed.r) { - this.setFromPayPro(parsed.r, function(err) { - if (err && addr && amount) { - self.setForm(addr, amount, message); - return addr; - } - }); - } else { - this.setForm(addr, amount, message); - return addr; - } - } - - }; - - this.onAddressChange = function(value) { - this.resetError(); - if (!value) return ''; - - if (this._paypro) - return value; - - if (value.indexOf('bitcoin:') === 0) { - return this.setFromUri(value); - } else if (/^https?:\/\//.test(value)) { - return this.setFromPayPro(value); - } else { - return value; - } - }; - - // History - - function strip(number) { - return (parseFloat(number.toPrecision(12))); - } - - this.getUnitName = function() { - return this.unitName; - }; - - this.getAlternativeIsoCode = function() { - return this.alternativeIsoCode; - }; - - this.openTxModal = function(btx) { - var self = this; - - $scope.btx = lodash.cloneDeep(btx); - $scope.self = self; - - $ionicModal.fromTemplateUrl('views/modals/tx-details.html', { - scope: $scope, - hideDelay: 500 - }).then(function(modal) { - $scope.txDetailsModal = modal; - $scope.txDetailsModal.show(); - }); - }; - - this.hasAction = function(actions, action) { - return actions.hasOwnProperty('create'); - }; - - this.sendMax = function(availableBalanceSat) { - if (availableBalanceSat == 0) { - this.error = gettext("Cannot create transaction. Insufficient funds"); - return; - } - - var self = this; - var fc = profileService.focusedClient; - this.error = null; - ongoingProcess.set('calculatingFee', true); - - $timeout(function() { - - feeService.getCurrentFeeValue(function(err, feePerKb) { - ongoingProcess.set('calculatingFee', false); - if (err || !lodash.isNumber(feePerKb)) { - self.error = gettext('Could not get fee value'); - return; - } - - var opts = {}; - opts.feePerKb = feePerKb; - opts.returnInputs = true; - var config = configService.getSync(); - opts.excludeUnconfirmedUtxos = !config.wallet.spendUnconfirmed; - ongoingProcess.set('retrivingInputs', true); - - fc.getSendMaxInfo(opts, function(err, resp) { - ongoingProcess.set('retrivingInputs', false); - - if (err) { - self.error = err; - $scope.$apply(); - return; - } - - if (resp.amount == 0) { - self.error = gettext("Not enough funds for fee"); - $scope.$apply(); - return; - } - - var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees", { - fee: profileService.formatAmount(resp.fee) + ' ' + self.unitName - }); - - var warningMsg = verifyExcludedUtxos(); - - if (!lodash.isEmpty(warningMsg)) - msg += '. \n' + warningMsg; - - confirmDialog.show(msg, function(confirmed) { - if (confirmed) { - self.sendMaxInfo = resp; - var amount = parseFloat((resp.amount * self.satToUnit).toFixed(self.unitDecimals)); - self.setForm(null, amount, null); - } else { - self.resetForm(); - } - }); - - function verifyExcludedUtxos() { - var warningMsg = []; - if (resp.utxosBelowFee > 0) { - warningMsg.push(gettextCatalog.getString("Note: a total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", { - amountBelowFeeStr: profileService.formatAmount(resp.amountBelowFee) + ' ' + self.unitName - })); - } - if (resp.utxosAboveMaxSize > 0) { - warningMsg.push(gettextCatalog.getString("Note: a total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded", { - amountAboveMaxSizeStr: profileService.formatAmount(resp.amountAboveMaxSize) + ' ' + self.unitName - })); - } - return warningMsg.join('\n'); - } - }); - }); - }, 10); - }; - - /* Start setup */ - lodash.assign(self, vanillaScope); - - this.bindTouchDown(); - if (profileService.focusedClient) { - this.setAddress(); - this.setSendFormInputs(); - } - -});