diff --git a/src/js/controllers/amount.js b/src/js/controllers/amount.js index 5e34d4c31..d7078a4ba 100644 --- a/src/js/controllers/amount.js +++ b/src/js/controllers/amount.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('amountController', function($scope, $filter, $timeout, $ionicScrollDelegate, $ionicHistory, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService, bwcError, payproService, profileService, bitcore, amazonService, glideraService) { +angular.module('copayApp.controllers').controller('amountController', function($scope, $filter, $timeout, $ionicScrollDelegate, $ionicHistory, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService, bwcError, payproService, profileService, bitcore, amazonService) { var unitToSatoshi; var satToUnit; var unitDecimals; @@ -14,9 +14,6 @@ angular.module('copayApp.controllers').controller('amountController', function($ }); $scope.$on("$ionicView.beforeEnter", function(event, data) { - // Glidera parameters - $scope.isGlidera = data.stateParams.isGlidera; - $scope.glideraAccessToken = data.stateParams.glideraAccessToken; // Go to... $scope.nextStep = data.stateParams.nextStep; @@ -30,26 +27,17 @@ angular.module('copayApp.controllers').controller('amountController', function($ $scope.toAddress = data.stateParams.toAddress; $scope.toName = data.stateParams.toName; $scope.toEmail = data.stateParams.toEmail; - $scope.showAlternativeAmount = !!$scope.cardId || !!$scope.isGlidera || !!$scope.nextStep; + $scope.showAlternativeAmount = !!$scope.cardId || !!$scope.nextStep; $scope.toColor = data.stateParams.toColor; $scope.showSendMax = false; $scope.customAmount = data.stateParams.customAmount; - if (!$scope.cardId && !$scope.isGlidera && !$scope.nextStep && !data.stateParams.toAddress) { + if (!$scope.cardId && !$scope.nextStep && !data.stateParams.toAddress) { $log.error('Bad params at amount') throw ('bad params'); } - if ($scope.isGlidera) { - glideraService.getLimits($scope.glideraAccessToken, function(err, limits) { - $scope.limits = limits; - $timeout(function() { - $scope.$apply(); - }); - }); - } - var reNr = /^[1234567890\.]$/; var reOp = /^[\*\+\-\/]$/; @@ -293,13 +281,6 @@ angular.module('copayApp.controllers').controller('amountController', function($ }); }); - } else if ($scope.isGlidera) { - var amount = $scope.showAlternativeAmount ? fromFiat(_amount) : _amount; - $state.transitionTo('tabs.buyandsell.glidera.confirm', { - toAmount: (amount * unitToSatoshi).toFixed(0), - isGlidera: $scope.isGlidera, - glideraAccessToken: $scope.glideraAccessToken - }); } else if ($scope.nextStep) { $state.transitionTo($scope.nextStep, { amount: _amount, diff --git a/src/js/controllers/buyGlidera.js b/src/js/controllers/buyGlidera.js new file mode 100644 index 000000000..7839685cc --- /dev/null +++ b/src/js/controllers/buyGlidera.js @@ -0,0 +1,165 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('buyGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, platformInfo) { + + var amount; + var currency; + + $scope.isCordova = platformInfo.isCordova; + + var showErrorAndBack = function(err) { + $scope.sendStatus = ''; + $log.error(err); + err = err.errors ? err.errors[0].message : err || ''; + popupService.showAlert('Error', err, function() { + $ionicHistory.goBack(); + }); + }; + + var showError = function(err) { + $scope.sendStatus = ''; + $log.error(err); + err = err.errors ? err.errors[0].message : err; + popupService.showAlert('Error', err); + }; + + var statusChangeHandler = function (processName, showName, isOn) { + $log.debug('statusChangeHandler: ', processName, showName, isOn); + if ( processName == 'buyingBitcoin' && !isOn) { + $scope.sendStatus = 'success'; + $timeout(function() { + $scope.$digest(); + }, 100); + } else if (showName) { + $scope.sendStatus = showName; + } + }; + + $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.isFiat = data.stateParams.currency ? true : false; + var parsedAmount = glideraService.parseAmount( + data.stateParams.amount, + data.stateParams.currency); + + amount = parsedAmount.amount; + currency = parsedAmount.currency; + $scope.amountUnitStr = parsedAmount.amountUnitStr; + + $scope.network = glideraService.getNetwork(); + $scope.wallets = profileService.getWallets({ + onlyComplete: true, + network: $scope.network + }); + $scope.wallet = $scope.wallets[0]; // Default first wallet + + ongoingProcess.set('connectingGlidera', true); + glideraService.init(function(err, data) { + if (err) { + ongoingProcess.set('connectingGlidera', false); + showErrorAndBack(err); + return; + } + $scope.token = data.token; + var price = {}; + if ($scope.isFiat) { + price['fiat'] = amount; + } else { + price['qty'] = amount; + } + glideraService.buyPrice($scope.token, price, function(err, buy) { + ongoingProcess.set('connectingGlidera', false); + if (err) { + showErrorAndBack(err); + return; + } + $scope.buyInfo = buy; + }); + }); + }); + + var ask2FaCode = function(mode, cb) { + if (mode != 'NONE') { + // SHOW PROMPT + var title = 'Please, enter the code below'; + var message; + if (mode == 'PIN') { + message = 'You have enabled PIN based two-factor authentication.'; + } else if (mode == 'AUTHENTICATOR') { + message = 'Use an authenticator app (Authy or Google Authenticator).'; + } else { + message = 'A SMS containing a confirmation code was sent to your phone.'; + } + popupService.showPrompt(title, message, null, function(twoFaCode) { + if (typeof twoFaCode == 'undefined') return cb(); + return cb(twoFaCode); + }); + } else { + return cb(); + } + }; + + $scope.buyConfirm = function() { + var message = 'Buy bitcoin for ' + amount + ' ' + currency; + var okText = 'Confirm'; + var cancelText = 'Cancel'; + popupService.showConfirm(null, message, okText, cancelText, function(ok) { + if (!ok) return; + ongoingProcess.set('buyingBitcoin', true, statusChangeHandler); + glideraService.get2faCode($scope.token, function(err, tfa) { + if (err) { + ongoingProcess.set('buyingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + ask2FaCode(tfa.mode, function(twoFaCode) { + if (tfa.mode != 'NONE' && lodash.isEmpty(twoFaCode)) { + ongoingProcess.set('buyingBitcoin', false, statusChangeHandler); + showError('No code entered'); + return; + } + + walletService.getAddress($scope.wallet, false, function(err, walletAddr) { + if (err) { + ongoingProcess.set('buyingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + var data = { + destinationAddress: walletAddr, + qty: $scope.buyInfo.qty, + priceUuid: $scope.buyInfo.priceUuid, + useCurrentPrice: false, + ip: null + }; + glideraService.buy($scope.token, twoFaCode, data, function(err, data) { + ongoingProcess.set('buyingBitcoin', false, statusChangeHandler); + if (err) return showError(err); + $log.info(data); + }); + }); + }); + }); + }); + }; + + $scope.showWalletSelector = function() { + $scope.walletSelectorTitle = 'Receive in'; + $scope.showWallets = true; + }; + + $scope.onWalletSelect = function(wallet) { + $scope.wallet = wallet; + }; + + $scope.goBackHome = function() { + $scope.sendStatus = ''; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $ionicHistory.clearHistory(); + $state.go('tabs.home').then(function() { + $state.transitionTo('tabs.buyandsell.glidera'); + }); + }; +}); diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index def38a854..64e54a6d7 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, glideraService, bwcError, bitpayCardService) { +angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, bitpayCardService) { var cachedTxp = {}; var toAmount; var isChromeApp = platformInfo.isChromeApp; @@ -11,10 +11,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.$on("$ionicView.beforeEnter", function(event, data) { - // Glidera parameters - $scope.isGlidera = data.stateParams.isGlidera; - $scope.glideraAccessToken = data.stateParams.glideraAccessToken; - toAmount = data.stateParams.toAmount; cachedSendMax = {}; $scope.useSendMax = data.stateParams.useSendMax == 'true' ? true : false; @@ -39,8 +35,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( var config = configService.getSync().wallet; var feeLevel = config.settings && config.settings.feeLevel ? config.settings.feeLevel : 'normal'; $scope.feeLevel = feeService.feeOpts[feeLevel]; - if ($scope.isGlidera) $scope.network = glideraService.getEnvironment(); - else $scope.network = (new bitcore.Address($scope.toAddress)).network.name; + $scope.network = (new bitcore.Address($scope.toAddress)).network.name; resetValues(); setwallets(); applyButtonText(); @@ -49,7 +44,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( function applyButtonText(multisig) { $scope.buttonText = $scope.isCordova ? gettextCatalog.getString('Slide') + ' ' : gettextCatalog.getString('Click') + ' '; - if ($scope.isGlidera || $scope.cardId) { + if ($scope.cardId) { $scope.buttonText += gettextCatalog.getString('to complete'); } else if ($scope.paypro) { $scope.buttonText += gettextCatalog.getString('to pay'); @@ -75,11 +70,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( return; } - if ($scope.isGlidera == 'buy') { - initConfirm(); - return; - } - var filteredWallets = []; var index = 0; var enoughFunds = false; @@ -161,8 +151,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.alternativeAmountStr = v; }); } - if ($scope.isGlidera == 'buy') $scope.getBuyPrice(); - if ($scope.isGlidera == 'sell') $scope.getSellPrice(); }; function resetValues() { @@ -271,7 +259,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( }); $scope.showWalletSelector = function() { - $scope.walletSelectorTitle = $scope.isGlidera == 'buy' ? 'Receive in' : $scope.isGlidera == 'sell' ? 'Sell From' : gettextCatalog.getString('Send from'); + $scope.walletSelectorTitle = gettextCatalog.getString('Send from'); if (!$scope.useSendMax && ($scope.insufficientFunds || $scope.noMatchingWallet)) return; $scope.showWallets = true; }; @@ -350,7 +338,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.wallet = wallet; $scope.fee = $scope.txp = null; - if ($scope.isGlidera) return; if (stop) { $timeout.cancel(stop); stop = null; @@ -476,47 +463,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( return; } - if ($scope.isGlidera) { - $scope.get2faCode(function(err, sent) { - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send confirmation code to your phone')); - return; - } - if (sent) { - var title = gettextCatalog.getString("Please, enter the code below"); - var message = gettextCatalog.getString("A SMS containing a confirmation code was sent to your phone."); - popupService.showPrompt(title, message, null, function(twoFaCode) { - if (typeof twoFaCode == 'undefined') return; - if ($scope.isGlidera == 'buy') { - $scope.buyRequest(wallet, twoFaCode, function(err, data) { - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err); - return; - } - $scope.sendStatus = 'success'; - $timeout(function() { - $scope.$digest(); - }); - }) - } - if ($scope.isGlidera == 'sell') { - $scope.sellRequest(wallet, twoFaCode, function(err, data) { - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err); - return; - } - $scope.sendStatus = 'success'; - $timeout(function() { - $scope.$digest(); - }); - }) - } - }); - } - }); - return; - } - ongoingProcess.set('creatingTx', true, onSendStatusChange); createTx(wallet, false, function(err, txp) { ongoingProcess.set('creatingTx', false, onSendStatusChange); @@ -587,7 +533,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.onSuccessConfirm = function() { var previousView = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName; var fromBitPayCard = previousView.match(/tabs.bitpayCard/) ? true : false; - var fromGlidera = previousView.match(/tabs.buyandsell.glidera/) ? true : false; $ionicHistory.nextViewOptions({ disableAnimate: true @@ -601,15 +546,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( id: $stateParams.cardId }); }, 100); - } else if (fromGlidera) { - $ionicHistory.nextViewOptions({ - disableAnimate: true, - historyRoot: true - }); - $ionicHistory.clearHistory(); - $state.go('tabs.home').then(function() { - $state.transitionTo('tabs.buyandsell.glidera'); - }); } else { $ionicHistory.nextViewOptions({ disableAnimate: true, @@ -622,162 +558,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( } }; - $scope.get2faCode = function(cb) { - ongoingProcess.set('sending2faCode', true); - $timeout(function() { - glideraService.get2faCode($scope.glideraAccessToken, function(err, sent) { - ongoingProcess.set('sending2faCode', false); - return cb(err, sent); - }); - }, 100); - }; - - $scope.buyRequest = function(wallet, twoFaCode, cb) { - ongoingProcess.set('buyingBitcoin', true); - $timeout(function() { - walletService.getAddress(wallet, false, function(err, walletAddr) { - if (err) { - ongoingProcess.set('buyingBitcoin', false); - popupService.showAlert(gettextCatalog.getString('Error'), bwcError.cb(err, 'Could not create address')); - return; - } - var data = { - destinationAddress: walletAddr, - qty: $scope.buyPrice.qty, - priceUuid: $scope.buyPrice.priceUuid, - useCurrentPrice: false, - ip: null - }; - glideraService.buy($scope.glideraAccessToken, twoFaCode, data, function(err, data) { - ongoingProcess.set('buyingBitcoin', false); - return cb(err, data); - }); - }); - }, 100); - }; - - $scope.sellRequest = function(wallet, twoFaCode, cb) { - var outputs = []; - var config = configService.getSync(); - var configWallet = config.wallet; - var walletSettings = configWallet.settings; - - ongoingProcess.set('creatingTx', true); - walletService.getAddress(wallet, null, function(err, refundAddress) { - if (!refundAddress) { - ongoingProcess.clear(); - popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, 'Could not create address')); - return; - } - glideraService.getSellAddress($scope.glideraAccessToken, function(err, sellAddress) { - if (!sellAddress || err) { - ongoingProcess.clear(); - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get the destination bitcoin address')); - return; - } - var amount = parseInt(($scope.sellPrice.qty * 100000000).toFixed(0)); - var comment = 'Glidera transaction'; - - outputs.push({ - 'toAddress': sellAddress, - 'amount': amount, - 'message': comment - }); - - var txp = { - toAddress: sellAddress, - amount: amount, - outputs: outputs, - message: comment, - payProUrl: null, - excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true, - feeLevel: walletSettings.feeLevel || 'normal', - customData: { - 'glideraToken': $scope.glideraAccessToken - } - }; - - walletService.createTx(wallet, txp, function(err, createdTxp) { - ongoingProcess.clear(); - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err)); - return; - } - walletService.prepare(wallet, function(err, password) { - if (err) { - ongoingProcess.clear(); - popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err)); - return; - } - ongoingProcess.set('signingTx', true); - walletService.publishTx(wallet, createdTxp, function(err, publishedTxp) { - if (err) { - ongoingProcess.clear(); - popupService.showAlert(gettextCatalog.getString('Error'), err.message ||  bwcError.msg(err)); - return; - } - - walletService.signTx(wallet, publishedTxp, password, function(err, signedTxp) { - if (err) { - ongoingProcess.clear(); - popupService.showAlert(gettextCatalog.getString('Error'), err.message ||  bwcError.msg(err)); - walletService.removeTx(wallet, signedTxp, function(err) { - if (err) $log.debug(err); - }); - return; - } - var rawTx = signedTxp.raw; - var data = { - refundAddress: refundAddress, - signedTransaction: rawTx, - priceUuid: $scope.sellPrice.priceUuid, - useCurrentPrice: $scope.sellPrice.priceUuid ? false : true, - ip: null - }; - ongoingProcess.set('sellingBitcoin', true); - glideraService.sell($scope.glideraAccessToken, twoFaCode, data, function(err, data) { - ongoingProcess.clear(); - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err.message ||  bwcError.msg(err)); - return; - } - return cb(err, data) - }); - }); - }); - }); - }); - }); - }); - } - - $scope.getBuyPrice = function() { - var satToBtc = 1 / 100000000; - var price = {}; - price.qty = (toAmount * satToBtc).toFixed(8); - glideraService.buyPrice($scope.glideraAccessToken, price, function(err, buyPrice) { - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), 'Could not get exchange information. Please, try again'); - return; - } - $scope.buyPrice = buyPrice; - }); - }; - - $scope.getSellPrice = function() { - var satToBtc = 1 / 100000000; - var price = {}; - price.qty = (toAmount * satToBtc).toFixed(8); - - glideraService.sellPrice($scope.glideraAccessToken, price, function(err, sellPrice) { - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), 'Could not get exchange information. Please, try again'); - return; - } - $scope.sellPrice = sellPrice; - }); - }; - function publishAndSign(wallet, txp, onSendStatusChange) { if (!wallet.canSign() && !wallet.isPrivKeyExternal()) { diff --git a/src/js/controllers/glidera.js b/src/js/controllers/glidera.js index d47721c67..7a2609430 100644 --- a/src/js/controllers/glidera.js +++ b/src/js/controllers/glidera.js @@ -1,72 +1,30 @@ 'use strict'; angular.module('copayApp.controllers').controller('glideraController', - function($scope, $timeout, $ionicModal, $log, storageService, glideraService, ongoingProcess, platformInfo, externalLinkService, popupService, gettextCatalog) { - - $scope.network = glideraService.getEnvironment(); + function($scope, $timeout, $ionicModal, $log, storageService, glideraService, ongoingProcess, platformInfo, externalLinkService, popupService, lodash) { $scope.openExternalLink = function(url) { externalLinkService.open(url); }; - var initGlidera = function(accessToken) { - $scope.token = accessToken; - $scope.permissions = null; - $scope.email = null; - $scope.personalInfo = null; - $scope.txs = null; - $scope.status = null; - $scope.limits = null; + var init = function() { + glideraService.init(function(err, data) { + if (err || lodash.isEmpty(data)) return; - $scope.connectingGlidera = true; - ongoingProcess.set('connectingGlidera', true); - glideraService.init($scope.token, function(err, glidera) { - ongoingProcess.set('connectingGlidera'); - $scope.connectingGlidera = false; - if (err || !glidera) { - if (err) popupService.showAlert(gettextCatalog.getString('Error'), err); - return; - } - $scope.token = glidera.token; - $scope.permissions = glidera.permissions; - $scope.update({ - fullUpdate: true + $scope.account['token'] = data.token; + $scope.account['status'] = data.status; + $scope.account['txs'] = data.txs; + + $timeout(function() { + $scope.$digest(); + $scope.update(); }); }); }; $scope.update = function(opts) { - if (!$scope.token || !$scope.permissions) return; - $log.debug('Updating Glidera Account...'); - var accessToken = $scope.token; - var permissions = $scope.permissions; - - opts = opts || {}; - - glideraService.getStatus(accessToken, function(err, data) { - $scope.status = data; - }); - - glideraService.getLimits(accessToken, function(err, limits) { - $scope.limits = limits; - }); - - if (permissions.transaction_history) { - glideraService.getTransactions(accessToken, function(err, data) { - $scope.txs = data; - }); - } - - if (permissions.view_email_address && opts.fullUpdate) { - glideraService.getEmail(accessToken, function(err, data) { - $scope.email = data.email; - }); - } - if (permissions.personal_info && opts.fullUpdate) { - glideraService.getPersonalInfo(accessToken, function(err, data) { - $scope.personalInfo = data; - }); - } + $log.debug('Updating Glidera...'); + glideraService.updateStatus($scope.account); }; $scope.getAuthenticateUrl = function() { @@ -75,29 +33,24 @@ angular.module('copayApp.controllers').controller('glideraController', $scope.submitOauthCode = function(code) { ongoingProcess.set('connectingGlidera', true); - $timeout(function() { - glideraService.getToken(code, function(err, data) { - ongoingProcess.set('connectingGlidera', false); - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err); - } else if (data && data.access_token) { - storageService.setGlideraToken($scope.network, data.access_token, function() { - initGlidera(data.access_token); - $timeout(function() { - $scope.$apply(); - }, 100); - }); - } - }); - }, 100); + glideraService.authorize(code, function(err, data) { + ongoingProcess.set('connectingGlidera', false); + if (err) { + popupService.showAlert('Authorisation error', err); + return; + } + $scope.account['token'] = data.token; + $scope.account['status'] = data.status; + init(); + }); }; - $scope.openTxModal = function(token, tx) { + $scope.openTxModal = function(tx) { $scope.tx = tx; - glideraService.getTransaction(token, tx.transactionUuid, function(err, tx) { + glideraService.getTransaction($scope.account.token, tx.transactionUuid, function(err, tx) { if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get transactions')); + popupService.showAlert('Error getting transaction', 'Could not get transactions'); return; } $scope.tx = tx; @@ -127,28 +80,27 @@ angular.module('copayApp.controllers').controller('glideraController', $scope.openSupportWindow = function() { var url = glideraService.getSupportUrl(); var optIn = true; - var title = gettextCatalog.getString('Glidera Support'); - var message = gettextCatalog.getString('You can email glidera at support@glidera.io for direct support, or you can contact Glidera on Twitter.'); - var okText = gettextCatalog.getString('Tweet @GlideraInc'); - var cancelText = gettextCatalog.getString('Go Back'); + var title = 'Glidera Support'; + var message = 'You can email glidera at support@glidera.io for direct support, or you can contact Glidera on Twitter.'; + var okText = 'Tweet @GlideraInc'; + var cancelText = 'Go Back'; externalLinkService.open(url, optIn, title, message, okText, cancelText); } - $scope.retry = function() { - $scope.connectingGlidera = true; - $scope.update({'fullUpdate': true}); - $timeout(function(){ - $scope.connectingGlidera = false; - }, 300); - } - $scope.toggleOauthForm = function() { $scope.showOauthForm = !$scope.showOauthForm; } $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.network = glideraService.getNetwork(); + $scope.currency = glideraService.getCurrency(); $scope.showOauthForm = false; - initGlidera(); + $scope.account = {}; + if (data.stateParams && data.stateParams.code) { + $scope.submitOauthCode(data.stateParams.code); + } else { + init(); + } }); }); diff --git a/src/js/controllers/glideraUri.js b/src/js/controllers/glideraUri.js deleted file mode 100644 index 0ebcbfae7..000000000 --- a/src/js/controllers/glideraUri.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; -angular.module('copayApp.controllers').controller('glideraUriController', - function($scope, $log, $stateParams, $timeout, glideraService, storageService, $state, ongoingProcess, popupService, gettextCatalog) { - - var submitOauthCode = function(code) { - $log.debug('Glidera Oauth Code:' + code); - $scope.network = glideraService.getEnvironment(); - ongoingProcess.set('connectingGlidera', true); - $timeout(function() { - glideraService.getToken(code, function(err, data) { - ongoingProcess.set('connectingGlidera', false); - if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err); - } else if (data && data.access_token) { - storageService.setGlideraToken($scope.network, data.access_token, function() { - $timeout(function() { - $state.go('tabs.buyandsell.glidera'); - $scope.$apply(); - }, 500); - }); - } - }); - }, 100); - }; - - $scope.$on("$ionicView.enter", function(event, data){ - if ($stateParams.url) { - var match = $stateParams.url.match(/code=(.+)/); - if (match && match[1]) { - submitOauthCode(match[1]); - return; - } - } - $log.error('Bad state: ' + JSON.stringify($stateParams)); - }); - }); diff --git a/src/js/controllers/preferencesGlidera.js b/src/js/controllers/preferencesGlidera.js index 8d18005a2..12469e00f 100644 --- a/src/js/controllers/preferencesGlidera.js +++ b/src/js/controllers/preferencesGlidera.js @@ -1,46 +1,12 @@ 'use strict'; angular.module('copayApp.controllers').controller('preferencesGlideraController', - function($scope, $log, $timeout, $state, $ionicHistory, ongoingProcess, glideraService, popupService, gettextCatalog) { - - $scope.update = function(opts) { - if (!$scope.token || !$scope.permissions) return; - $log.debug('Updating Glidera Account...'); - var accessToken = $scope.token; - var permissions = $scope.permissions; - - opts = opts || {}; - - glideraService.getStatus(accessToken, function(err, data) { - $scope.status = data; - }); - - glideraService.getLimits(accessToken, function(err, limits) { - $scope.limits = limits; - }); - - if (permissions.transaction_history) { - glideraService.getTransactions(accessToken, function(err, data) { - $scope.txs = data; - }); - } - - if (permissions.view_email_address && opts.fullUpdate) { - glideraService.getEmail(accessToken, function(err, data) { - $scope.email = data; - }); - } - if (permissions.personal_info && opts.fullUpdate) { - glideraService.getPersonalInfo(accessToken, function(err, data) { - $scope.personalInfo = data; - }); - } - }; + function($scope, $timeout, $state, $ionicHistory, glideraService, popupService) { $scope.revokeToken = function() { popupService.showConfirm('Glidera', 'Are you sure you would like to log out of your Glidera account?', null, null, function(res) { if (res) { - glideraService.removeToken(function() { + glideraService.remove(function() { $ionicHistory.clearHistory(); $timeout(function() { $state.go('tabs.home'); @@ -50,21 +16,20 @@ angular.module('copayApp.controllers').controller('preferencesGlideraController' }); }; - $scope.$on("$ionicView.enter", function(event, data){ - $scope.network = glideraService.getEnvironment(); + $scope.$on("$ionicView.afterEnter", function(event, data){ + glideraService.updateStatus($scope.account); + }); - ongoingProcess.set('connectingGlidera', true); - glideraService.init($scope.token, function(err, glidera) { - ongoingProcess.set('connectingGlidera'); + $scope.$on("$ionicView.beforeEnter", function(event, data){ + $scope.account = {}; + glideraService.init(function(err, glidera) { if (err || !glidera) { - if (err) popupService.showAlert(gettextCatalog.getString('Error'), err); + if (err) popupService.showAlert('Error connecting Glidera', err); return; } - $scope.token = glidera.token; - $scope.permissions = glidera.permissions; - $scope.update({ - fullUpdate: true - }); + $scope.account['token'] = glidera.token; + $scope.account['permissions'] = glidera.permissions; + $scope.account['status'] = glidera.status; }); }); diff --git a/src/js/controllers/sellGlidera.js b/src/js/controllers/sellGlidera.js new file mode 100644 index 000000000..3028e0df3 --- /dev/null +++ b/src/js/controllers/sellGlidera.js @@ -0,0 +1,233 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('sellGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, configService, platformInfo) { + + var amount; + var currency; + + $scope.isCordova = platformInfo.isCordova; + + var showErrorAndBack = function(err) { + $scope.sendStatus = ''; + $log.error(err); + err = err.errors ? err.errors[0].message : err; + popupService.showAlert('Error', err, function() { + $ionicHistory.goBack(); + }); + }; + + var showError = function(err) { + $scope.sendStatus = ''; + $log.error(err); + err = err.errors ? err.errors[0].message : err; + popupService.showAlert('Error', err); + }; + + var statusChangeHandler = function (processName, showName, isOn) { + $log.debug('statusChangeHandler: ', processName, showName, isOn); + if ( processName == 'sellingBitcoin' && !isOn) { + $scope.sendStatus = 'success'; + $timeout(function() { + $scope.$digest(); + }, 100); + } else if (showName) { + $scope.sendStatus = showName; + } + }; + + $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.isFiat = data.stateParams.currency ? true : false; + var parsedAmount = glideraService.parseAmount( + data.stateParams.amount, + data.stateParams.currency); + + amount = parsedAmount.amount; + currency = parsedAmount.currency; + $scope.amountUnitStr = parsedAmount.amountUnitStr; + + $scope.network = glideraService.getNetwork(); + $scope.wallets = profileService.getWallets({ + m: 1, // Only 1-signature wallet + onlyComplete: true, + network: $scope.network + }); + $scope.wallet = $scope.wallets[0]; // Default first wallet + + ongoingProcess.set('connectingGlidera', true); + glideraService.init(function(err, data) { + if (err) { + ongoingProcess.set('connectingGlidera', false); + showErrorAndBack(err); + return; + } + $scope.token = data.token; + var price = {}; + if ($scope.isFiat) { + price['fiat'] = amount; + } else { + price['qty'] = amount; + } + glideraService.sellPrice($scope.token, price, function(err, sell) { + ongoingProcess.set('connectingGlidera', false); + if (err) { + showErrorAndBack(err); + return; + } + $scope.sellInfo = sell; + }); + }); + }); + + var ask2FaCode = function(mode, cb) { + if (mode != 'NONE') { + // SHOW PROMPT + var title = 'Please, enter the code below'; + var message; + if (mode == 'PIN') { + message = 'You have enabled PIN based two-factor authentication.'; + } else if (mode == 'AUTHENTICATOR') { + message = 'Use an authenticator app (Authy or Google Authenticator).'; + } else { + message = 'A SMS containing a confirmation code was sent to your phone.'; + } + popupService.showPrompt(title, message, null, function(twoFaCode) { + if (typeof twoFaCode == 'undefined') return cb(); + return cb(twoFaCode); + }); + } else { + return cb(); + } + }; + + $scope.sellConfirm = function() { + var message = 'Sell bitcoin for ' + amount + ' ' + currency; + var okText = 'Confirm'; + var cancelText = 'Cancel'; + popupService.showConfirm(null, message, okText, cancelText, function(ok) { + if (!ok) return; + ongoingProcess.set('sellingBitcoin', true, statusChangeHandler); + glideraService.get2faCode($scope.token, function(err, tfa) { + if (err) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + ask2FaCode(tfa.mode, function(twoFaCode) { + if (tfa.mode != 'NONE' && lodash.isEmpty(twoFaCode)) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError('No code entered'); + return; + } + + var outputs = []; + var config = configService.getSync(); + var configWallet = config.wallet; + var walletSettings = configWallet.settings; + + walletService.getAddress($scope.wallet, null, function(err, refundAddress) { + if (!refundAddress) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError('Could not create address'); + return; + } + glideraService.getSellAddress($scope.token, function(err, sellAddress) { + if (!sellAddress || err) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + var amount = parseInt(($scope.sellInfo.qty * 100000000).toFixed(0)); + var comment = 'Glidera transaction'; + + outputs.push({ + 'toAddress': sellAddress, + 'amount': amount, + 'message': comment + }); + + var txp = { + toAddress: sellAddress, + amount: amount, + outputs: outputs, + message: comment, + payProUrl: null, + excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true, + feeLevel: walletSettings.feeLevel || 'normal', + customData: { + 'glideraToken': $scope.token + } + }; + + walletService.createTx($scope.wallet, txp, function(err, createdTxp) { + if (err) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + walletService.prepare($scope.wallet, function(err, password) { + if (err) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + walletService.publishTx($scope.wallet, createdTxp, function(err, publishedTxp) { + if (err) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError(err); + return; + } + walletService.signTx($scope.wallet, publishedTxp, password, function(err, signedTxp) { + if (err) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + showError(err); + walletService.removeTx($scope.wallet, signedTxp, function(err) { + if (err) $log.debug(err); + }); + return; + } + var rawTx = signedTxp.raw; + var data = { + refundAddress: refundAddress, + signedTransaction: rawTx, + priceUuid: $scope.sellInfo.priceUuid, + useCurrentPrice: $scope.sellInfo.priceUuid ? false : true, + ip: null + }; + glideraService.sell($scope.token, twoFaCode, data, function(err, data) { + ongoingProcess.set('sellingBitcoin', false, statusChangeHandler); + if (err) return showError(err); + $log.info(data); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }; + + $scope.showWalletSelector = function() { + $scope.walletSelectorTitle = 'Sell From'; + $scope.showWallets = true; + }; + + $scope.onWalletSelect = function(wallet) { + $scope.wallet = wallet; + }; + + $scope.goBackHome = function() { + $scope.sendStatus = ''; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $ionicHistory.clearHistory(); + $state.go('tabs.home').then(function() { + $state.transitionTo('tabs.buyandsell.glidera'); + }); + }; + +}); diff --git a/src/js/routes.js b/src/js/routes.js index 9f54c75c6..0b160e193 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -140,11 +140,6 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr url: '/uri-payment/:url', templateUrl: 'views/paymentUri.html' }) - .state('uriglidera', { - url: '/uri-glidera/:url', - controller: 'glideraUriController', - templateUrl: 'views/glideraUri.html' - }) /* * @@ -883,7 +878,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr */ .state('tabs.buyandsell.glidera', { - url: '/glidera', + url: '/glidera/:code', views: { 'tab-home@tabs': { controller: 'glideraController', @@ -893,7 +888,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }) .state('tabs.buyandsell.glidera.amount', { - url: '/amount/:isGlidera/:glideraAccessToken', + url: '/amount/:nextStep/:currency', views: { 'tab-home@tabs': { controller: 'amountController', @@ -901,12 +896,21 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } } }) - .state('tabs.buyandsell.glidera.confirm', { - url: '/confirm/:toAmount/:isGlidera/:glideraAccessToken', + .state('tabs.buyandsell.glidera.buy', { + url: '/buy/:amount/:currency', views: { 'tab-home@tabs': { - controller: 'confirmController', - templateUrl: 'views/confirm.html' + controller: 'buyGlideraController', + templateUrl: 'views/buyGlidera.html' + } + } + }) + .state('tabs.buyandsell.glidera.sell', { + url: '/sell/:amount/:currency', + views: { + 'tab-home@tabs': { + controller: 'sellGlideraController', + templateUrl: 'views/sellGlidera.html' } } }) diff --git a/src/js/services/glideraService.js b/src/js/services/glideraService.js index 987ae5845..e7bb92977 100644 --- a/src/js/services/glideraService.js +++ b/src/js/services/glideraService.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('glideraService', function($http, $log, $window, platformInfo, storageService, buyAndSellService) { +angular.module('copayApp.services').factory('glideraService', function($http, $log, $window, $filter, platformInfo, storageService, buyAndSellService, lodash, configService, txFormatService) { var root = {}; var credentials = {}; var isCordova = platformInfo.isCordova; @@ -45,10 +45,38 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l }; }; - root.getEnvironment = function() { + root.getNetwork = function() { return credentials.NETWORK; }; + root.getCurrency = function() { + return 'USD'; + }; + + root.parseAmount = function(amount, currency) { + var config = configService.getSync().wallet.settings; + var satToBtc = 1 / 100000000; + var unitToSatoshi = config.unitToSatoshi; + var amountUnitStr; + + // IF 'USD' + if (currency) { + amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency; + } else { + var amountSat = parseInt((amount * unitToSatoshi).toFixed(0)); + amountUnitStr = txFormatService.formatAmountStr(amountSat); + // convert unit to BTC + amount = (amountSat * satToBtc).toFixed(8); + currency = 'BTC'; + } + + return { + amount: amount, + currency: currency, + amountUnitStr: amountUnitStr + }; + }; + root.getSignupUrl = function() { return credentials.HOST + '/register'; } @@ -61,10 +89,14 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return credentials.HOST + '/oauth2/auth?response_type=code&client_id=' + credentials.CLIENT_ID + '&redirect_uri=' + credentials.REDIRECT_URI; }; - root.removeToken = function(cb) { + root.remove = function(cb) { storageService.removeGlideraToken(credentials.NETWORK, function() { - buyAndSellService.updateLink('glidera', false); - return cb(); + storageService.removeGlideraPermissions(credentials.NETWORK, function() { + storageService.removeGlideraStatus(credentials.NETWORK, function() { + buyAndSellService.updateLink('glidera', false); + return cb(); + }); + }); }); }; @@ -87,15 +119,39 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l $http(req).then(function(data) { $log.info('Glidera Authorization Access Token: SUCCESS'); - // Show pending task from the UI - storageService.setNextStep('BuyAndSell', 'true', function(err) {}); return cb(null, data.data); }, function(data) { $log.error('Glidera Authorization Access Token: ERROR ' + data.statusText); - return cb('Glidera Authorization Access Token: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; + root.authorize = function(code, cb) { + root.getToken(code, function(err, data) { + if (err) return cb(err); + if (data && !data.access_token) return cb('No access token'); + var accessToken = data.access_token; + root.getAccessTokenPermissions(accessToken, function(err, p) { + if (err) return cb(err); + root.getStatus(accessToken, function(err, status) { + if (err) $log.error(err); + storageService.setGlideraToken(credentials.NETWORK, accessToken, function() { + storageService.setGlideraPermissions(credentials.NETWORK, JSON.stringify(p), function() { + storageService.setGlideraStatus(credentials.NETWORK, JSON.stringify(status), function() { + return cb(null, { + token: accessToken, + permissions: p, + status: status + }); + }); + }); + }); + }); + }); + }); + }; + var _get = function(endpoint, token) { return { method: 'GET', @@ -115,7 +171,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Access Token Permissions: ERROR ' + data.statusText); - return cb('Glidera Access Token Permissions: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -126,7 +183,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Get Email: ERROR ' + data.statusText); - return cb('Glidera Get Email: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -137,7 +195,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Get Personal Info: ERROR ' + data.statusText); - return cb('Glidera Get Personal Info: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -148,7 +207,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera User Status: ERROR ' + data.statusText); - return cb('Glidera User Status: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -159,7 +219,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Transaction Limits: ERROR ' + data.statusText); - return cb('Glidera Transaction Limits: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -170,7 +231,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data.transactions); }, function(data) { $log.error('Glidera Transactions: ERROR ' + data.statusText); - return cb('Glidera Transactions: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -182,7 +244,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Transaction: ERROR ' + data.statusText); - return cb('Glidera Transaction: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -193,23 +256,20 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data.sellAddress); }, function(data) { $log.error('Glidera Create Sell Address: ERROR ' + data.statusText); - return cb('Glidera Create Sell Address: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; root.get2faCode = function(token, cb) { - if (!token) { - $log.error('Glidera Sent 2FA code by SMS: ERROR Invalid Token'); - return cb('Invalid Token'); - } - + if (!token) return cb('Invalid Token'); $http(_get('/authentication/get2faCode', token)).then(function(data) { - - $log.info('Glidera Sent 2FA code by SMS: SUCCESS'); - return cb(null, data.status == 200 ? true : false); + $log.info('Glidera 2FA code: SUCCESS'); + return cb(null, data.data); }, function(data) { - $log.error('Glidera Sent 2FA code by SMS: ERROR ' + data.statusText); - return cb('Glidera Sent 2FA code by SMS: ERROR ' + data.statusText); + $log.error('Glidera 2FA code: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -221,7 +281,7 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer ' + token, - '2FA_CODE': twoFaCode + 'X-2FA-CODE': twoFaCode }, data: data }; @@ -237,7 +297,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Sell Price: ERROR ' + data.statusText); - return cb('Glidera Sell Price: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -254,7 +315,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Sell Request: ERROR ' + data.statusText); - return cb('Glidera Sell Request: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -268,7 +330,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Buy Price: ERROR ' + data.statusText); - return cb('Glidera Buy Price: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; @@ -285,44 +348,84 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l return cb(null, data.data); }, function(data) { $log.error('Glidera Buy Request: ERROR ' + data.statusText); - return cb('Glidera Buy Request: ERROR ' + data.statusText); + var message = data.data && data.data.message ? data.data.message : data.statusText; + return cb(message); }); }; - root.init = function(accessToken, cb) { - $log.debug('Init Glidera...'); - - var glidera = { - token: null, - permissions: null + root.init = function(cb) { + if (lodash.isEmpty(credentials.CLIENT_ID)) { + return cb('Glidera is Disabled'); } + $log.debug('Trying to initialise Glidera...'); - var getToken = function(cb) { - if (accessToken) { - cb(null, accessToken); - } else { - storageService.getGlideraToken(credentials.NETWORK, cb); - } - }; - - getToken(function(err, accessToken) { - if (err || !accessToken) return cb(); - else { - buyAndSellService.updateLink('glidera', true); - - root.getAccessTokenPermissions(accessToken, function(err, p) { - if (err) { - return cb(err); - } else { - glidera.token = accessToken; - glidera.permissions = p; - return cb(null, glidera); - } + storageService.getGlideraToken(credentials.NETWORK, function(err, accessToken) { + if (err || lodash.isEmpty(accessToken)) return cb(); + + storageService.getGlideraPermissions(credentials.NETWORK, function(err, permissions) { + if (lodash.isString(permissions)) permissions = JSON.parse(permissions); + storageService.getGlideraStatus(credentials.NETWORK, function(err, status) { + if (lodash.isString(status)) status = JSON.parse(status); + storageService.getGlideraTxs(credentials.NETWORK, function(err, txs) { + if (lodash.isString(txs)) txs = JSON.parse(txs); + buyAndSellService.updateLink('glidera', true); + return cb(null, { + token: accessToken, + permissions: permissions, + status: status, + txs: txs + }); + }); }); - } + }); }); }; + root.updateStatus = function(data) { + storageService.getGlideraToken(credentials.NETWORK, function(err, accessToken) { + if (err) return; + root.getAccessTokenPermissions(accessToken, function(err, permissions) { + if (err) return; + storageService.setGlideraPermissions(credentials.NETWORK, JSON.stringify(permissions), function() {}); + data.permissions = permissions; + + data.price = {}; + root.buyPrice(accessToken, {qty: 1}, function(err, buy) { + data.price['buy'] = buy.price; + }); + root.sellPrice(accessToken, {qty: 1}, function(err, sell) { + data.price['sell'] = sell.price; + }); + + root.getStatus(accessToken, function(err, status) { + data.status = status; + storageService.setGlideraStatus(credentials.NETWORK, JSON.stringify(status), function() {}); + }); + + root.getLimits(accessToken, function(err, limits) { + data.limits = limits; + }); + + if (permissions.transaction_history) { + root.getTransactions(accessToken, function(err, txs) { + storageService.setGlideraTxs(credentials.NETWORK, JSON.stringify(txs), function() {}); + data.txs = txs; + }); + } + + if (permissions.view_email_address) { + root.getEmail(accessToken, function(err, email) { + data.email = email; + }); + } + if (permissions.personal_info) { + root.getPersonalInfo(accessToken, function(err, info) { + data.personalInfo = info; + }); + } + }); + }); + }; var register = function() { if (isWindowsPhoneApp) return; diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index c9543536e..2863f2f1a 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -122,9 +122,23 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat goToAmountPage(data); } } else if (data && data.indexOf(appConfigService.name + '://glidera') === 0) { - return $state.go('uriglidera', { - url: data + var code = getParameterByName('code', data); + $ionicHistory.nextViewOptions({ + disableAnimate: true }); + $state.go('tabs.home', {}, { + 'reload': true, + 'notify': $state.current.name == 'tabs.home' ? false : true + }).then(function() { + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $state.transitionTo('tabs.buyandsell.glidera', { + code: code + }); + }); + return true; + } else if (data && data.indexOf(appConfigService.name + '://coinbase') === 0) { var code = getParameterByName('code', data); $ionicHistory.nextViewOptions({ diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 668e8c66a..60510d98f 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -247,6 +247,42 @@ angular.module('copayApp.services') storage.remove('glideraToken-' + network, cb); }; + root.setGlideraPermissions = function(network, p, cb) { + storage.set('glideraPermissions-' + network, p, cb); + }; + + root.getGlideraPermissions = function(network, cb) { + storage.get('glideraPermissions-' + network, cb); + }; + + root.removeGlideraPermissions = function(network, cb) { + storage.remove('glideraPermissions-' + network, cb); + }; + + root.setGlideraStatus = function(network, status, cb) { + storage.set('glideraStatus-' + network, status, cb); + }; + + root.getGlideraStatus = function(network, cb) { + storage.get('glideraStatus-' + network, cb); + }; + + root.removeGlideraStatus = function(network, cb) { + storage.remove('glideraStatus-' + network, cb); + }; + + root.setGlideraTxs = function(network, txs, cb) { + storage.set('glideraTxs-' + network, txs, cb); + }; + + root.getGlideraTxs = function(network, cb) { + storage.get('glideraTxs-' + network, cb); + }; + + root.removeGlideraTxs = function(network, cb) { + storage.remove('glideraTxs-' + network, cb); + }; + root.setCoinbaseRefreshToken = function(network, token, cb) { storage.set('coinbaseRefreshToken-' + network, token, cb); }; diff --git a/src/sass/views/integrations/glidera.scss b/src/sass/views/integrations/glidera.scss index fea75b498..0dd003c3a 100644 --- a/src/sass/views/integrations/glidera.scss +++ b/src/sass/views/integrations/glidera.scss @@ -1,4 +1,136 @@ #glidera { + $item-lateral-padding: 20px; + $item-vertical-padding: 10px; + $item-border-color: #EFEFEF; + $item-label-color: #6C6C6E; + @extend .deflash-blue; + + .spinner svg { + stroke: #0067c8; + fill: #0067c8; + } + + .add-bottom-for-cta { + bottom: 92px; + } + .head { + padding: 30px $item-lateral-padding 4rem; + border-top: 0; + + .sending-label { + display: flex; + font-size: 18px; + align-items: center; + margin-bottom: 1.5rem; + + img { + margin-right: 1rem; + height: 35px; + width: 35px; + } + + span { + text-transform: capitalize; + } + } + .amount-label{ + line-height: 30px; + .amount{ + font-size: 38px; + margin-bottom: .5rem; + + > .unit { + font-family: "Roboto-Light"; + } + } + .alternative { + font-size: 16px; + font-family: "Roboto-Light"; + color: #9B9B9B; + } + } + } + .item { + border-color: $item-border-color; + } + .info { + .badge { + border-radius: 0; + padding: .5rem; + } + .item { + color: #4A4A4A; + padding-top: $item-vertical-padding; + padding-bottom: $item-vertical-padding; + padding-left: $item-lateral-padding; + + &:not(.item-icon-right) { + padding-right: $item-lateral-padding; + } + + .label { + font-size: 14px; + color: $item-label-color; + margin-bottom: 8px; + } + + .capitalized { + text-transform: capitalize; + } + + .wallet .big-icon-svg > .bg { + height: 24px; + width: 24px; + padding: 2px; + box-shadow: none; + vertical-align: middle; + } + + .total-amount { + font-weight: bold; + } + + &.single-line { + display: flex; + align-items: center; + padding-top: 17px; + padding-bottom: 17px; + + .label { + margin: 0; + flex-grow: 1; + } + } + } + .item-divider { + padding-top: 1.2rem; + color: $item-label-color; + font-size: 15px; + } + .wallet { + display: flex; + align-items: center; + padding: .2rem 0; + margin-bottom: 5px; + + ~ .bp-arrow-right { + top: 14px; + } + + > i { + padding: 0; + position: static; + + > img { + height: 24px; + width: 24px; + padding: 2px; + margin-right: .7rem; + box-shadow: none; + } + } + } + } .glidera-lead { margin: 2rem 1rem; color: $dark-gray; diff --git a/www/views/buyGlidera.html b/www/views/buyGlidera.html new file mode 100644 index 000000000..6f33c08af --- /dev/null +++ b/www/views/buyGlidera.html @@ -0,0 +1,103 @@ + + + + + Buy bitcoin + + + + +
+ +
+
+ buy bitcoin + Buying +
+
+
{{amountUnitStr}}
+
+ {{buyInfo.subtotal}} {{buyInfo.currency}} + {{buyInfo.qty}} BTC + @ ${{buyInfo.price}} per BTC +
+
+
+ +
+ +
+
Receive in
+
+ + + + {{wallet ? wallet.name : '...'}} +
+ +
+ +
+ Transaction details +
+
+ Expires + + {{buyInfo.expires | amCalendar}} + +
+
+ Fees + + {{buyInfo.fees}} {{buyInfo.currency}} + +
+
+ Total to pay + + {{buyInfo.total}} {{buyInfo.currency}} + +
+
+
+ +
+ + + Confirm purchase + + + Slide to buy + + + Bought +
+ A transfer has been initiated from your bank account. Your bitcoins should arrive to your wallet in 2-4 business day +
+
+ + + +
diff --git a/www/views/buyandsell.html b/www/views/buyandsell.html index 7b5b72618..d43d047ae 100644 --- a/www/views/buyandsell.html +++ b/www/views/buyandsell.html @@ -17,7 +17,7 @@
- {{service.location}} + {{service.location}}
diff --git a/www/views/confirm.html b/www/views/confirm.html index 54d56c87b..c1a22bb03 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -12,10 +12,8 @@
- Sending + Sending Sending maximum amount - Buying - Selling
{{displayAmount || '...'}} {{displayUnit}}
@@ -31,16 +29,13 @@
- To - From - To + To - +
-
@@ -58,9 +53,7 @@
- From - To - From + From
@@ -75,47 +68,19 @@
- + Add Memo {{description}} -
+
{{'Fee' | translate}}: {{feeLevel | translate}} {{fee || '...'}}
-
- Information -
-
- Buy {{buyPrice.subtotal|currency:'':2}} {{buyPrice.currency}} in Bitcoin at {{buyPrice.price}} {{buyPrice.currency}}/BTC -
-
- Fiat will be immediately withdrawn from your bank account. -
-
- The bitcoins will be purchased and deposited to "{{wallet.name || '...' }}" wallet in 2-4 business days. -
-
-
-
- Information -
-
- Sell {{sellPrice.subtotal|currency:'':2}} {{sellPrice.currency}} in Bitcoin at {{sellPrice.price|currency:'':2}} {{sellPrice.currency}}/BTC -
-
- Fiat will be deposited in your bank account in 4-6 business days. -
-
- Bitcoins will be immediately sent from your "{{wallet.name || '...' }}" wallet to Glidera. -
-
-
No wallets available
@@ -150,10 +115,6 @@ Payment Sent Proposal Created Transaction created -
- A transfer has been initiated from your bank account. Your bitcoins should arrive to your wallet in 2-4 business day - A transfer has been initiated to your bank account. Should arrive in 4-6 business days -
Glidera - - - -
- The Glidera integration is currently disabled. -
-
- Testnet wallets only work with Glidera Sandbox Accounts. -
+
-
Glidera's exchange service is available in the United States, and can take 1-2 weeks to buy or sell bitcoin.
-
If you have trouble, contact Glidera support for direct assistance.
+
Glidera's exchange service is available in the United States, and can take 1-2 weeks to buy or sell bitcoin.
+
If you have trouble, contact Glidera support for direct assistance.
- - + +
@@ -43,54 +38,60 @@ - +
- +
-
Please complete your account verification on Glidera's website. If you have trouble, contact Glidera's support for direct assistance.
+
Please complete your account verification on Glidera's website. If you have trouble, contact Glidera's support for direct assistance.
- - + +
- +
- +
- -
+
Activity
- diff --git a/www/views/preferencesGlidera.html b/www/views/preferencesGlidera.html index a93bd1f80..99de7e7ac 100644 --- a/www/views/preferencesGlidera.html +++ b/www/views/preferencesGlidera.html @@ -8,55 +8,55 @@
    -
    +
    Permissions
  • Email - {{permissions.view_email_address}} + {{account.permissions.view_email_address}}
  • Personal Information - {{permissions.personal_info}} + {{account.permissions.personal_info}}
  • Buy/Sell - {{permissions.transact}} + {{account.permissions.transact}}
  • Transaction History - {{permissions.transaction_history}} + {{account.permissions.transaction_history}}
  • -
    +
    Email
  • Email - {{email.email}} + {{account.email.email}}
  • Active - {{email.userEmailIsSetup}} + {{account.email.userEmailIsSetup}}
  • -
    +
    Personal Information
    @@ -64,73 +64,73 @@
  • First Name - {{personalInfo.firstName}} + {{account.personalInfo.firstName}}
  • Middle Name - {{personalInfo.middleName}} + {{account.personalInfo.middleName}}
  • Last Name - {{personalInfo.lastName}} + {{account.personalInfo.lastName}}
  • Birth Date - {{personalInfo.birthDate}} + {{account.personalInfo.birthDate}}
  • Address 1 - {{personalInfo.address1}} + {{account.personalInfo.address1}}
  • Address 2 - {{personalInfo.address2}} + {{account.personalInfo.address2}}
  • City - {{personalInfo.city}} + {{account.personalInfo.city}}
  • State - {{personalInfo.state}} + {{account.personalInfo.state}}
  • ZIP Code - {{personalInfo.zipCode}} + {{account.personalInfo.zipCode}}
  • Country - {{personalInfo.countryCode}} + {{account.personalInfo.countryCode}}
  • Occupation - {{personalInfo.occupation}} + {{account.personalInfo.occupation}}
  • Basic Information State - {{personalInfo.basicInfoState}} + {{account.personalInfo.basicInfoState}}
  • @@ -143,56 +143,56 @@
  • Buy/Sell - {{status.userCanTransact}} + {{account.status.userCanTransact}}
  • Buy - {{status.userCanBuy}} + {{account.status.userCanBuy}}
  • Sell - {{status.userCanSell}} + {{account.status.userCanSell}}
  • Email Is Setup - {{status.userEmailIsSetup}} + {{account.status.userEmailIsSetup}}
  • Phone Is Setup - {{status.userPhoneIsSetup}} + {{account.status.userPhoneIsSetup}}
  • Bank Account Is Setup - {{status.userBankAccountIsSetup}} + {{account.status.userBankAccountIsSetup}}
  • Personal Information State - {{status.personalInfoState}} + {{account.status.personalInfoState}}
  • Bank Account State - {{status.bankAccountState}} + {{account.status.bankAccountState}}
  • Country - {{status.country}} + {{account.status.country}}
  • @@ -205,55 +205,55 @@
  • Daily Buy - {{limits.dailyBuy|currency:'':2}} {{limits.currency}} + {{account.limits.dailyBuy|currency:'':2}} {{limits.currency}}
  • Daily Sell - {{limits.dailySell|currency:'':2}} {{limits.currency}} + {{account.limits.dailySell|currency:'':2}} {{limits.currency}}
  • Monthly Buy - {{limits.monthlyBuy|currency:'':2}} {{limits.currency}} + {{account.limits.monthlyBuy|currency:'':2}} {{limits.currency}}
  • Monthly Sell - {{limits.monthlySell|currency:'':2}} {{limits.currency}} + {{account.limits.monthlySell|currency:'':2}} {{limits.currency}}
  • Daily Buy Remaining - {{limits.dailyBuyRemaining|currency:'':2}} {{limits.currency}} + {{account.limits.dailyBuyRemaining|currency:'':2}} {{limits.currency}}
  • Daily Sell Remaining - {{limits.dailySellRemaining|currency:'':2}} {{limits.currency}} + {{account.limits.dailySellRemaining|currency:'':2}} {{limits.currency}}
  • Monthly Buy Remaining - {{limits.monthlyBuyRemaining|currency:'':2}} {{limits.currency}} + {{account.limits.monthlyBuyRemaining|currency:'':2}} {{limits.currency}}
  • Monthly Sell Remaining - {{limits.monthlySellRemaining|currency:'':2}} {{limits.currency}} + {{account.limits.monthlySellRemaining|currency:'':2}} {{limits.currency}}
  • Buy/Sell Disabled (pending first transaction) - {{limits.transactDisabledPendingFirstTransaction}} + {{account.limits.transactDisabledPendingFirstTransaction}}
  • diff --git a/www/views/sellGlidera.html b/www/views/sellGlidera.html new file mode 100644 index 000000000..02767126c --- /dev/null +++ b/www/views/sellGlidera.html @@ -0,0 +1,104 @@ + + + + + Sell bitcoin + + + + +
    + +
    +
    + sell bitcoin + Selling +
    +
    +
    {{amountUnitStr}}
    +
    + {{sellInfo.subtotal}} {{sellInfo.currency}} + {{sellInfo.qty}} BTC + @ ${{sellInfo.price}} per BTC +
    +
    +
    + +
    + +
    +
    From
    +
    + + + + {{wallet ? wallet.name : '...'}} +
    + +
    + +
    + Transaction details +
    +
    + Expires + + {{sellInfo.expires | amCalendar}} + +
    +
    + Fees + + {{sellInfo.fees}} {{sellInfo.currency}} + +
    +
    + Total to receive + + {{sellInfo.total}} {{sellInfo.currency}} + +
    +
    +
    + +
    + + + Confirm sale + + + Slide to sell + + + Funds sent to Glidera Account +
    + The transaction is not yet confirmed, and will show as "Pending" in your Activity. The bitcoin sale will be + completed automatically once it is confirmed by Glidera. +
    +
    + + + +