Merge pull request #3145 from cmgustavo/feat/glidera-integration

Feat/glidera integration
This commit is contained in:
Matias Alejo Garcia 2015-09-09 14:44:48 -03:00
commit a9a49f5007
33 changed files with 1856 additions and 249 deletions

View file

@ -24,214 +24,159 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-minus-circle:before {
content: "\e62c";
.icon-sell-btc:before {
content: "\e632";
}
.icon-plus-circle:before {
content: "\e62d";
.icon-buy-btc:before {
content: "\e631";
}
.icon-close-circle:before {
content: "\e62e";
}
.icon-checkmark-circle:before {
content: "\e62b";
}
.icon-circle:before {
content: "\e629";
}
.icon-circle-active:before {
content: "\e627";
}
.icon-scan:before {
content: "\e62a";
}
.icon-trash:before {
content: "\e626";
}
.icon-wallet:before {
content: "\e622";
}
.icon-history:before {
content: "\e623";
}
.icon-reference:before {
content: "\e621";
}
.icon-bell:before {
content: "\e61c";
}
.icon-trash:before {
content: "\e626";
}
.icon-wallet:before {
content: "\e622";
}
.icon-history:before {
content: "\e623";
}
.icon-reference:before {
content: "\e621";
}
.icon-bell:before {
content: "\e61c";
}
.icon-receive:before {
content: "\e625";
}
.icon-wrench:before {
content: "\e61d";
}
.icon-download:before {
content: "\e61e";
}
.icon-upload:before {
content: "\e61f";
}
.icon-power:before {
content: "\e620";
}
.icon-forward:before {
content: "\e624";
}
.icon-compose:before {
content: "\e610";
}
.icon-contact:before {
content: "\e611";
}
.icon-email:before {
content: "\e612";
}
.icon-gear:before {
content: "\e613";
}
.icon-home:before {
content: "\e614";
}
.icon-locked:before {
content: "\e615";
}
.icon-paperplane:before {
content: "\e617";
}
.icon-people:before {
content: "\e618";
}
.icon-person:before {
content: "\e619";
}
.icon-pricetag:before {
content: "\e61a";
}
.icon-pricetags:before {
content: "\e61b";
}
.icon-bitcoin:before {
content: "\e60f";
}
.icon-usd:before {
content: "\e616";
}
.icon-erase:before {
content: "\e628";
}
.icon-receive2:before {
content: "\e62f";
}
.icon-arrow-left:before {
content: "\e600";
}
.icon-arrow-down:before {
content: "\e601";
}
.icon-arrow-up:before {
content: "\e602";
}
.icon-arrow-right:before {
content: "\e603";
}
.icon-arrow-left2:before {
content: "\e604";
}
.icon-arrow-down2:before {
content: "\e605";
}
.icon-arrow-up2:before {
content: "\e606";
}
.icon-arrow-right2:before {
content: "\e607";
}
.icon-arrow-left3:before {
content: "\e608";
}
.icon-arrow-down3:before {
content: "\e609";
}
.icon-arrow-up3:before {
content: "\e60a";
}
.icon-arrow-right3:before {
content: "\e60b";
}
.icon-arrow-left4:before {
content: "\e60c";
}
.icon-arrow-down4:before {
content: "\e60d";
}
.icon-arrow-up4:before {
content: "\e60e";
}
.icon-bank:before {
content: "\e630";
}
.icon-minus-circle:before {
content: "\e62c";
}
.icon-plus-circle:before {
content: "\e62d";
}
.icon-close-circle:before {
content: "\e62e";
}
.icon-checkmark-circle:before {
content: "\e62b";
}
.icon-circle:before {
content: "\e629";
}
.icon-circle-active:before {
content: "\e627";
}
.icon-circle-active:before {
content: "\e627";
}
.icon-scan:before {
content: "\e62a";
}
.icon-trash:before {
content: "\e626";
}
.icon-wallet:before {
content: "\e622";
}
.icon-history:before {
content: "\e623";
}
.icon-reference:before {
content: "\e621";
}
.icon-bell:before {
content: "\e61c";
}
.icon-receive:before {
content: "\e625";
}
.icon-wrench:before {
content: "\e61d";
}
.icon-download:before {
content: "\e61e";
}
.icon-upload:before {
content: "\e61f";
}
.icon-power:before {
content: "\e620";
}
.icon-forward:before {
content: "\e624";
}
.icon-compose:before {
content: "\e610";
}
.icon-contact:before {
content: "\e611";
}
.icon-email:before {
content: "\e612";
}
.icon-gear:before {
content: "\e613";
}
.icon-home:before {
content: "\e614";
}
.icon-locked:before {
content: "\e615";
}
.icon-paperplane:before {
content: "\e617";
}
.icon-people:before {
content: "\e618";
}
.icon-person:before {
content: "\e619";
}
.icon-pricetag:before {
content: "\e61a";
}
.icon-pricetags:before {
content: "\e61b";
}
.icon-bitcoin:before {
content: "\e60f";
}
.icon-usd:before {
content: "\e616";
}

View file

@ -410,7 +410,6 @@ ul.manage li {
.line-t {
border-top: 1px solid #E9E9EC;
padding-top: 0.5rem;
}
.line-b {
@ -1098,7 +1097,16 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
}
.preferences-icon {
padding: 0.6rem 0.8rem !important;
width: auto;
height: 40px;
}
@media only screen and (max-width: 40em) {
.preferences-icon {
width: 40px;
height: 40px;
padding: 0.55rem !important;
}
}
.alertModal {

View file

@ -0,0 +1,80 @@
'use strict';
angular.module('copayApp.controllers').controller('buyGlideraController',
function($scope, $timeout, profileService, addressService, glideraService, gettext, gettextCatalog, bwsError) {
this.addr = {};
this.show2faCodeInput = null;
this.error = null;
this.success = null;
this.loading = null;
this.getBuyPrice = function(token, price) {
var self = this;
if (!price || (price && !price.qty && !price.fiat)) {
this.buyPrice = null;
return;
}
glideraService.buyPrice(token, price, function(err, buyPrice) {
if (err) {
self.error = gettext('Could not get exchange information. Please, try again.');
}
else {
self.buyPrice = buyPrice;
}
});
};
this.get2faCode = function(token) {
var self = this;
this.loading = gettext('Sending 2FA code...');
$timeout(function() {
glideraService.get2faCode(token, function(err, sent) {
self.loading = null;
if (err) {
self.error = gettext('Could not send confirmation code to your phone');
}
else {
self.error = null;
self.show2faCodeInput = sent;
}
});
}, 100);
};
this.sendRequest = function(token, permissions, twoFaCode) {
var fc = profileService.focusedClient;
if (!fc) return;
var self = this;
self.error = null;
addressService.getAddress(fc.credentials.walletId, null, function(err, addr) {
if (!addr) {
self.error = bwsError.msg(err);
$scope.$apply();
}
else {
self.loading = gettext('Buying bitcoin...');
var data = {
destinationAddress: addr,
qty: self.buyPrice.qty,
priceUuid: self.buyPrice.priceUuid,
useCurrentPrice: false,
ip: null
};
$timeout(function() {
glideraService.buy(token, twoFaCode, data, function(err, data) {
self.loading = null;
if (err) {
self.error = err;
}
else {
self.success = data;
$scope.$emit('Local/GlideraTx');
}
});
}, 100);
}
});
};
});

View file

@ -0,0 +1,76 @@
'use strict';
angular.module('copayApp.controllers').controller('glideraController',
function($scope, $timeout, $modal, profileService, configService, storageService, glideraService, isChromeApp) {
var config = configService.getSync().wallet.settings;
this.getAuthenticateUrl = function() {
return glideraService.getOauthCodeUrl();
};
this.submitOauthCode = function(code) {
var fc = profileService.focusedClient;
var self = this;
this.loading = true;
this.error = null;
$timeout(function() {
glideraService.getToken(code, function(err, data) {
self.loading = null;
if (err) {
self.error = err;
$timeout(function() {
$scope.$apply();
}, 100);
}
else if (data && data.access_token) {
storageService.setGlideraToken(fc.credentials.network, data.access_token, function() {
$scope.$emit('Local/GlideraTokenUpdated', data.access_token);
$timeout(function() {
$scope.$apply();
}, 100);
});
}
});
}, 100);
};
// DISABLE ANIMATION ON CHROMEAPP
if (isChromeApp) {
var animatedSlideRight = 'full';
}
else {
var animatedSlideRight = 'full animated slideInRight';
}
this.openTxModal = function(token, tx) {
var self = this;
var fc = profileService.focusedClient;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.tx = tx;
$scope.settings = config;
$scope.color = fc.backgroundColor;
glideraService.getTransaction(token, tx.transactionUuid, function(error, tx) {
$scope.tx = tx;
});
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
};
var modalInstance = $modal.open({
templateUrl: 'views/modals/glidera-tx-details.html',
windowClass: animatedSlideRight,
controller: ModalInstanceCtrl,
});
modalInstance.result.finally(function() {
var m = angular.element(document.getElementsByClassName('reveal-modal'));
m.addClass('slideOutRight');
});
};
});

View file

@ -0,0 +1,37 @@
'use strict';
angular.module('copayApp.controllers').controller('glideraUriController',
function($scope, $stateParams, $timeout, profileService, glideraService, storageService, go) {
this.submitOauthCode = function(code) {
var fc = profileService.focusedClient;
var self = this;
this.loading = true;
this.error = null;
$timeout(function() {
glideraService.getToken(code, function(err, data) {
self.loading = null;
if (err) {
self.error = err;
$timeout(function() {
$scope.$apply();
}, 100);
}
else if (data && data.access_token) {
storageService.setGlideraToken(fc.credentials.network, data.access_token, function() {
$scope.$emit('Local/GlideraTokenUpdated', data.access_token);
$timeout(function() {
go.path('glidera');
$scope.$apply();
}, 100);
});
}
});
}, 100);
};
this.checkCode = function() {
this.code = $stateParams.code;
this.submitOauthCode(this.code);
};
});

View file

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit, addonManager, feeService, isChromeApp, bwsError, utilService, $state) {
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit, addonManager, feeService, isChromeApp, bwsError, utilService, $state, glideraService) {
var self = this;
self.isCordova = isCordova;
self.onGoingProcess = {};
@ -113,6 +113,13 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.pendingTxProposalsCountForUs = null;
self.setSpendUnconfirmed();
self.glideraToken = null;
self.glideraError = null;
self.glideraPermissions = null;
self.glideraEmail = null;
self.glideraPersonalInfo = null;
self.glideraTxs = null;
$timeout(function() {
self.hasProfile = true;
self.noFocusedWallet = false;
@ -134,6 +141,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.copayers = [];
self.updateColor();
self.updateAlias();
self.initGlidera();
storageService.getBackupFlag(self.walletId, function(err, val) {
self.needsBackup = self.network == 'testnet' ? false : !val;
@ -145,18 +153,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.setTab = function(tab, reset, tries) {
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);
}
}
if (self.tab === tab && !reset)
return;
@ -166,30 +162,27 @@ angular.module('copayApp.controllers').controller('indexController', function($r
}, 300);
}
if (!self.tab || !$state.is('walletHome'))
if (!self.tab)
self.tab = 'walletHome';
go.path('walletHome', 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(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';
}
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);
});
self.tab = tab;
$rootScope.$emit('Local/TabChanged', tab);
};
@ -400,6 +393,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.setOngoingProcess('updatingPendingTxps', true);
$log.debug('Updating PendingTxps');
fc.getTxProposals({}, function(err, txps) {
console.log('[index.js:395]',txps); //TODO
self.setOngoingProcess('updatingPendingTxps', false);
if (err) {
self.handleError(err);
@ -843,6 +837,79 @@ angular.module('copayApp.controllers').controller('indexController', function($r
}), 'name');
};
self.initGlidera = function(accessToken) {
if (self.isShared) return;
self.glideraStatus = null;
glideraService.setCredentials(self.network);
var getToken = function(cb) {
if (accessToken) {
cb(null, accessToken);
} else {
storageService.getGlideraToken(self.network, cb);
}
};
getToken(function(err, accessToken) {
if (err || !accessToken) return;
else {
self.glideraLoading = gettext('Connecting to Glidera...');
glideraService.getAccessTokenPermissions(accessToken, function(err, p) {
self.glideraLoading = null;
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) {
self.glideraLoadingHistory = gettext('Getting Glidera transactions...');
glideraService.getTransactions(accessToken, function(err, data) {
self.glideraLoadingHistory = null;
self.glideraTxs = data;
});
}
if (permissions.view_email_address && opts.fullUpdate) {
self.glideraLoadingEmail = gettext('Getting Glidera Email...');
glideraService.getEmail(accessToken, function(err, data) {
self.glideraLoadingEmail = null;
self.glideraEmail = data.email;
});
}
if (permissions.personal_info && opts.fullUpdate) {
self.glideraLoadingPersonalInfo = gettext('Getting Glidera Personal Information...');
glideraService.getPersonalInfo(accessToken, function(err, data) {
self.glideraLoadingPersonalInfo = null;
self.glideraPersonalInfo = data;
});
}
};
// UX event handlers
$rootScope.$on('Local/ColorUpdated', function(event) {
self.updateColor();
@ -892,6 +959,18 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
});
$rootScope.$on('Local/GlideraTokenUpdated', function(event, accessToken) {
self.initGlidera(accessToken);
});
$rootScope.$on('Local/GlideraTx', function(event, accessToken, permissions) {
self.updateGlidera();
});
$rootScope.$on('Local/GlideraError', function(event) {
self.debouncedUpdate();
});
$rootScope.$on('Local/UnitSettingUpdated', function(event) {
self.updateAll();
self.updateTxHistory();
@ -989,8 +1068,8 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
});
lodash.each(['NewTxProposal', 'TxProposalFinallyRejected', 'TxProposalRemoved',
'Local/NewTxProposal', 'Local/TxProposalAction', 'ScanFinished'
lodash.each(['NewTxProposal', 'TxProposalFinallyRejected', 'TxProposalRemoved', 'NewOutgoingTxByThirdParty',
'Local/NewTxProposal', 'Local/TxProposalAction', 'ScanFinished', 'Local/GlideraTx'
], function(eventName) {
$rootScope.$on(eventName, function(event, untilItChanges) {
self.updateAll({

View file

@ -0,0 +1,61 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesGlideraController',
function($scope, $modal, $timeout, profileService, applicationService, glideraService, storageService) {
this.getEmail = function(token) {
var self = this;
glideraService.getEmail(token, function(error, data) {
self.email = data;
});
};
this.getPersonalInfo = function(token) {
var self = this;
glideraService.getPersonalInfo(token, function(error, info) {
self.personalInfo = info;
});
};
this.getStatus = function(token) {
var self = this;
glideraService.getStatus(token, function(error, data) {
self.status = data;
});
};
this.getLimits = function(token) {
var self = this;
glideraService.getLimits(token, function(error, limits) {
self.limits = limits;
});
};
this.revokeToken = function() {
var fc = profileService.focusedClient;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.ok = function() {
$modalInstance.close(true);
};
$scope.cancel = function() {
$modalInstance.dismiss();
};
};
var modalInstance = $modal.open({
templateUrl: 'views/modals/glidera-confirmation.html',
windowClass: 'full',
controller: ModalInstanceCtrl
});
modalInstance.result.then(function(ok) {
if (ok) {
storageService.removeGlideraToken(fc.credentials.network, function() {
$timeout(function() {
applicationService.restart();
}, 100);
});
}
});
};
});

View file

@ -0,0 +1,158 @@
'use strict';
angular.module('copayApp.controllers').controller('sellGlideraController',
function($scope, $timeout, $log, gettext, gettextCatalog, configService, profileService, addressService, feeService, glideraService, bwsError) {
var config = configService.getSync();
this.data = {};
this.show2faCodeInput = null;
this.success = null;
this.error = null;
this.loading = null;
this.currentSpendUnconfirmed = config.wallet.spendUnconfirmed;
this.currentFeeLevel = config.wallet.settings.feeLevel || 'normal';
this.getSellPrice = function(token, price) {
var self = this;
if (!price || (price && !price.qty && !price.fiat)) {
this.error = null;
this.sellPrice = null;
return;
}
glideraService.sellPrice(token, price, function(err, sellPrice) {
if (err) {
self.error = gettext('Could not get exchange information. Please, try again.');
}
else {
self.error = null;
self.sellPrice = sellPrice;
}
});
};
this.get2faCode = function(token) {
var self = this;
this.loading = gettext('Sending 2FA code...');
$timeout(function() {
glideraService.get2faCode(token, function(err, sent) {
self.loading = null;
if (err) {
self.error = gettext('Could not send confirmation code to your phone');
}
else {
self.show2faCodeInput = sent;
}
});
}, 100);
};
this.createTx = function(token, permissions, twoFaCode) {
var self = this;
var fc = profileService.focusedClient;
self.error = null;
this.loading = gettext('Selling Bitcoin...');
$timeout(function() {
addressService.getAddress(fc.credentials.walletId, null, function(err, refundAddress) {
if (!refundAddress) {
self.loading = null;
self.error = bwsError.msg(err);
return;
}
glideraService.getSellAddress(token, function(error, sellAddress) {
if (!sellAddress) {
self.loading = null;
self.error = gettext('Could not get the destination bitcoin address');
return;
}
var amount = parseInt((self.sellPrice.qty * 100000000).toFixed(0));
feeService.getCurrentFeeValue(self.currentFeeLevel, function(err, feePerKb) {
if (err) $log.debug(err);
fc.sendTxProposal({
toAddress: sellAddress,
amount: amount,
message: 'Glidera transaction',
customData: {'glideraToken': token},
payProUrl: null,
feePerKb: feePerKb,
excludeUnconfirmedUtxos: self.currentSpendUnconfirmed ? false : true
}, function(err, txp) {
if (err) {
profileService.lockFC();
$log.error(err);
$timeout(function() {
self.loading = null;
self.error = bwsError.msg(err, gettextCatalog.getString('Error'));
}, 1);
return;
}
if (!fc.canSign()) {
self.loading = null;
$log.info('No signing proposal: No private key');
return;
}
_signTx(txp, function(err, txp, rawTx) {
profileService.lockFC();
if (err) {
self.loading = null;
self.error = err;
$scope.$apply();
}
else {
var data = {
refundAddress: refundAddress,
signedTransaction: rawTx,
priceUuid: self.sellPrice.priceUuid,
useCurrentPrice: self.sellPrice.priceUuid ? false : true,
ip: null
};
glideraService.sell(token, twoFaCode, data, function(err, data) {
self.loading = null;
if (err) {
self.error = err;
fc.removeTxProposal(txp, function(err, txpb) {
$timeout(function() {
$scope.$emit('Local/GlideraError');
}, 100);
});
}
else {
self.success = data;
$scope.$emit('Local/GlideraTx');
}
});
}
});
});
});
});
});
}, 100);
};
var _signTx = function(txp, cb) {
var self = this;
var fc = profileService.focusedClient;
fc.signTxProposal(txp, function(err, signedTx) {
profileService.lockFC();
if (err) {
err = bwsError.msg(err, gettextCatalog.getString('Could not accept payment'));
return cb(err);
}
else {
if (signedTx.status == 'accepted') {
return cb(null, txp, signedTx.raw);
} else {
return cb(gettext('The transaction could not be signed'));
}
}
});
};
});

View file

@ -30,8 +30,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (isChromeApp) {
var animatedSlideUp = 'full';
var animatedSlideRight = 'full';
}
else {
} else {
var animatedSlideUp = 'full animated slideInUp';
var animatedSlideRight = 'full animated slideInRight';
}
@ -174,18 +173,30 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
});
};
this.openTxpModal = function(tx, copayers) {
var GLIDERA_LOCK_TIME = 6 * 60 * 60 ;
// isGlidera flag is a security mesure so glidera status is not
// only determined by the tx.message
this.openTxpModal = function(tx, copayers, isGlidera) {
var fc = profileService.focusedClient;
var refreshUntilItChanges = false;
var currentSpendUnconfirmed = $scope.currentSpendUnconfirmed;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.error = null;
$scope.tx = tx;
$scope.copayers = copayers
$scope.copayerId = fc.credentials.copayerId;
$scope.canSign = fc.canSign();
$scope.loading = null;
$scope.color = fc.backgroundColor;
// ToDo: use tx.customData instead of tx.message
if (tx.message === 'Glidera transaction' && isGlidera) {
tx.isGlidera = true;
if (tx.canBeRemoved) {
tx.canBeRemoved = (Date.now()/1000 - (tx.ts || tx.createdOn)) > GLIDERA_LOCK_TIME;
}
}
$scope.tx = tx;
refreshUntilItChanges = false;
$scope.currentSpendUnconfirmed = currentSpendUnconfirmed;

View file

@ -9,8 +9,14 @@ angular.element(document).ready(function() {
var handleBitcoinURI = function(url) {
if (!url) return;
if (url.indexOf('glidera') != -1) {
url = '#/uri-glidera' + url.replace('bitcoin://glidera', '');
}
else {
url = '#/uri-payment/' + url;
}
setTimeout(function() {
window.location = '#/uri-payment/' + url;
window.location = url;
}, 1000);
};

View file

@ -288,6 +288,56 @@ angular
},
}
})
.state('uriglidera', {
url: '/uri-glidera?code',
needProfile: true,
views: {
'main': {
templateUrl: 'views/glideraUri.html'
},
}
})
.state('glidera', {
url: '/glidera',
walletShouldBeComplete: true,
needProfile: true,
views: {
'main': {
templateUrl: 'views/glidera.html'
},
}
})
.state('buyGlidera', {
url: '/buy',
walletShouldBeComplete: true,
needProfile: true,
views: {
'main': {
templateUrl: 'views/buyGlidera.html'
},
}
})
.state('sellGlidera', {
url: '/sell',
walletShouldBeComplete: true,
needProfile: true,
views: {
'main': {
templateUrl: 'views/sellGlidera.html'
},
}
})
.state('preferencesGlidera', {
url: '/preferencesGlidera',
walletShouldBeComplete: true,
needProfile: true,
views: {
'main': {
templateUrl: 'views/preferencesGlidera.html'
},
}
})
.state('preferencesAdvanced', {
url: '/preferencesAdvanced',
@ -486,11 +536,16 @@ angular
copayers: -1,
cordova: -1,
payment: -1,
uriglidera: -1,
preferences: 11,
glidera: 11,
preferencesColor: 12,
backup: 12,
preferencesAdvanced: 12,
buyGlidera: 12,
sellGlidera: 12,
preferencesGlidera: 12,
delete: 13,
preferencesLanguage: 12,
preferencesUnit: 12,

View file

@ -0,0 +1,253 @@
'use strict';
angular.module('copayApp.services').factory('glideraService', function($http, $log, isCordova) {
var root = {};
var credentials = {};
root.setCredentials = function(network) {
if (network == 'testnet') {
credentials.HOST = 'https://sandbox.glidera.io';
if (isCordova) {
credentials.REDIRECT_URI = 'bitcoin://glidera';
credentials.CLIENT_ID = 'dfc56e4336e32bb8ba46dde34f3d7d6d';
credentials.CLIENT_SECRET = '5eb679058f6c7eb81123162323d4fba5';
}
else {
credentials.REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob';
credentials.CLIENT_ID = '9915b6ffa6dc3baffb87135ed3873d49';
credentials.CLIENT_SECRET = 'd74eda05b9c6a228fd5c85cfbd0eb7eb';
}
}
else {
credentials.HOST = 'https://glidera.io';
credentials.REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob';
credentials.CLIENT_ID = '';
credentials.CLIENT_SECRET = '';
};
};
root.getOauthCodeUrl = function() {
return credentials.HOST
+ '/oauth2/auth?response_type=code&client_id='
+ credentials.CLIENT_ID
+ '&redirect_uri='
+ credentials.REDIRECT_URI;
};
root.getToken = function(code, cb) {
var req = {
method: 'POST',
url: credentials.HOST + '/api/v1/oauth/token',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
data: {
grant_type : 'authorization_code',
code: code,
client_id : credentials.CLIENT_ID,
client_secret: credentials.CLIENT_SECRET,
redirect_uri: credentials.REDIRECT_URI
}
};
$http(req).then(function(data) {
$log.info('Glidera Authorization Access Token: SUCCESS');
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 _get = function(endpoint, token) {
return {
method: 'GET',
url: credentials.HOST + '/api/v1' + endpoint,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer ' + token
}
};
};
root.getAccessTokenPermissions = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/oauth/token', token)).then(function(data) {
$log.info('Glidera Access Token Permissions: SUCCESS');
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);
});
};
root.getEmail = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/user/email', token)).then(function(data) {
$log.info('Glidera Get Email: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Get Email: ERROR ' + data.statusText);
return cb('Glidera Get Email: ERROR ' + data.statusText);
});
};
root.getPersonalInfo = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/user/personalinfo', token)).then(function(data) {
$log.info('Glidera Get Personal Info: SUCCESS');
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);
});
};
root.getStatus = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/user/status', token)).then(function(data) {
$log.info('Glidera User Status: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera User Status: ERROR ' + data.statusText);
return cb('Glidera User Status: ERROR ' + data.statusText);
});
};
root.getLimits = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/user/limits', token)).then(function(data) {
$log.info('Glidera Transaction Limits: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Transaction Limits: ERROR ' + data.statusText);
return cb('Glidera Transaction Limits: ERROR ' + data.statusText);
});
};
root.getTransactions = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/transaction', token)).then(function(data) {
$log.info('Glidera Transactions: SUCCESS');
return cb(null, data.data.transactions);
}, function(data) {
$log.error('Glidera Transactions: ERROR ' + data.statusText);
return cb('Glidera Transactions: ERROR ' + data.statusText);
});
};
root.getTransaction = function(token, txid, cb) {
if (!token) return cb('Invalid Token');
if (!txid) return cb('TxId required');
$http(_get('/transaction/' + txid, token)).then(function(data) {
$log.info('Glidera Transaction: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Transaction: ERROR ' + data.statusText);
return cb('Glidera Transaction: ERROR ' + data.statusText);
});
};
root.getSellAddress = function(token, cb) {
if (!token) return cb('Invalid Token');
$http(_get('/user/create_sell_address', token)).then(function(data) {
$log.info('Glidera Create Sell Address: SUCCESS');
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);
});
};
root.get2faCode = function(token, cb) {
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);
}, function(data) {
$log.error('Glidera Sent 2FA code by SMS: ERROR ' + data.statusText);
return cb('Glidera Sent 2FA code by SMS: ERROR ' + data.statusText);
});
};
var _post = function(endpoint, token, twoFaCode, data) {
return {
method: 'POST',
url: credentials.HOST + '/api/v1' + endpoint,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer ' + token,
'2FA_CODE': twoFaCode
},
data: data
};
};
root.sellPrice = function(token, price, cb) {
var data = {
qty: price.qty,
fiat: price.fiat
};
$http(_post('/prices/sell', token, null, data)).then(function(data) {
$log.info('Glidera Sell Price: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Sell Price: ERROR ' + data.statusText);
return cb('Glidera Sell Price: ERROR ' + data.statusText);
});
};
root.sell = function(token, twoFaCode, data, cb) {
var data = {
refundAddress: data.refundAddress,
signedTransaction: data.signedTransaction,
priceUuid: data.priceUuid,
useCurrentPrice: data.useCurrentPrice,
ip: data.ip
};
$http(_post('/sell', token, twoFaCode, data)).then(function(data) {
$log.info('Glidera Sell: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Sell Request: ERROR ' + data.statusText);
return cb('Glidera Sell Request: ERROR ' + data.statusText);
});
};
root.buyPrice = function(token, price, cb) {
var data = {
qty: price.qty,
fiat: price.fiat
};
$http(_post('/prices/buy', token, null, data)).then(function(data) {
$log.info('Glidera Buy Price: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Buy Price: ERROR ' + data.statusText);
return cb('Glidera Buy Price: ERROR ' + data.statusText);
});
};
root.buy = function(token, twoFaCode, data, cb) {
var data = {
destinationAddress: data.destinationAddress,
qty: data.qty,
priceUuid: data.priceUuid,
useCurrentPrice: data.useCurrentPrice,
ip: data.ip
};
$http(_post('/buy', token, twoFaCode, data)).then(function(data) {
$log.info('Glidera Buy: SUCCESS');
return cb(null, data.data);
}, function(data) {
$log.error('Glidera Buy Request: ERROR ' + data.statusText);
return cb('Glidera Buy Request: ERROR ' + data.statusText);
});
};
return root;
});

View file

@ -29,12 +29,13 @@ angular.module('copayApp.services').factory('go', function($window, $rootScope,
}
};
root.openExternalLink = function(url) {
root.openExternalLink = function(url, target) {
if (nodeWebkit.isDefined()) {
nodeWebkit.openExternalLink(url);
}
else {
var ref = window.open(url, '_blank', 'location=no');
target = target || '_blank';
var ref = window.open(url, target, 'location=no');
}
};
@ -89,8 +90,8 @@ angular.module('copayApp.services').factory('go', function($window, $rootScope,
root.path(path);
};
$rootScope.openExternalLink = function(url) {
root.openExternalLink(url);
$rootScope.openExternalLink = function(url, target) {
root.openExternalLink(url, target);
};

View file

@ -192,5 +192,17 @@ angular.module('copayApp.services')
storage.get('remotePrefStored', cb);
};
root.setGlideraToken = function(network, token, cb) {
storage.set('glideraToken-' + network, token, cb);
};
root.getGlideraToken = function(network, cb) {
storage.get('glideraToken-' + network, cb);
};
root.removeGlideraToken = function(network, cb) {
storage.remove('glideraToken-' + network, cb);
};
return root;
});