195 lines
6 KiB
JavaScript
195 lines
6 KiB
JavaScript
'use strict';
|
|
|
|
angular.module('copayApp.services').factory('bitpayService', function($log, $http, platformInfo, appIdentityService, bitauthService, storageService, gettextCatalog, popupService) {
|
|
var root = {};
|
|
|
|
var NETWORK = 'livenet';
|
|
var BITPAY_API_URL = NETWORK == 'livenet' ? 'https://bitpay.com' : 'https://test.bitpay.com';
|
|
|
|
root.getEnvironment = function() {
|
|
return {
|
|
network: NETWORK
|
|
};
|
|
};
|
|
|
|
/*
|
|
* Pair this app with the bitpay server using the specified pairing data.
|
|
* An app identity will be created if one does not already exist.
|
|
* Pairing data is provided by an input URI provided by the bitpay server.
|
|
*
|
|
* pairData - data needed to complete the pairing process
|
|
* {
|
|
* secret: shared pairing secret
|
|
* email: email address associated with bitpay account
|
|
* otp: two-factor one-time use password
|
|
* }
|
|
*
|
|
* pairingReason - text string to be embedded into popup message. If `null` then the reason
|
|
* message is not shown to the UI.
|
|
* "To {{reason}} you must pair this app with your BitPay account ({{email}})."
|
|
*
|
|
* cb - callback after completion
|
|
* callback(err, paired, apiContext)
|
|
*
|
|
* err - something unexpected happened which prevented the pairing
|
|
*
|
|
* paired - boolean indicating whether the pairing was compledted by the user
|
|
*
|
|
* apiContext - the context needed for making future api calls
|
|
* {
|
|
* token: api token for use in future calls
|
|
* pairData: the input pair data
|
|
* appIdentity: the identity of this app
|
|
* }
|
|
*/
|
|
root.pair = function(pairData, pairingReason, cb) {
|
|
checkOtp(pairData, function(otp) {
|
|
pairData.otp = otp;
|
|
var deviceName = 'Unknown device';
|
|
if (platformInfo.isNW) {
|
|
deviceName = require('os').platform();
|
|
} else if (platformInfo.isCordova) {
|
|
deviceName = device.model;
|
|
}
|
|
var json = {
|
|
method: 'createToken',
|
|
params: {
|
|
secret: pairData.secret,
|
|
version: 2,
|
|
deviceName: deviceName,
|
|
code: pairData.otp
|
|
}
|
|
};
|
|
appIdentityService.getIdentity(root.getEnvironment().network, function(err, appIdentity) {
|
|
if (err) return cb(err);
|
|
$http(_postAuth('/api/v2/', json, appIdentity)).then(function(data) {
|
|
if (data && data.data.error) return cb(data.data.error);
|
|
$log.info('BitPay service BitAuth create token: SUCCESS');
|
|
var title = gettextCatalog.getString('Add BitPay Account?');
|
|
var msgDetail = 'Add this BitPay account ({{email}})?';
|
|
if (pairingReason) {
|
|
msgDetail = 'To {{reason}} you must first add your BitPay account.<br/><br/>{{email}}';
|
|
}
|
|
var msg = gettextCatalog.getString(msgDetail, {
|
|
reason: pairingReason,
|
|
email: pairData.email
|
|
});
|
|
var ok = gettextCatalog.getString('Add Account');
|
|
var cancel = gettextCatalog.getString('Go back');
|
|
popupService.showConfirm(title, msg, ok, cancel, function(res) {
|
|
if (res) {
|
|
var acctData = {
|
|
token: data.data.data,
|
|
email: pairData.email
|
|
};
|
|
setBitpayAccount(acctData, function(err) {
|
|
if (err) return cb(err);
|
|
return cb(null, true, {
|
|
token: acctData.token,
|
|
pairData: pairData,
|
|
appIdentity: appIdentity
|
|
});
|
|
});
|
|
} else {
|
|
$log.info('User cancelled BitPay pairing process');
|
|
return cb(null, false);
|
|
}
|
|
});
|
|
}, function(data) {
|
|
return cb(_setError('BitPay service BitAuth create token: ERROR ', data));
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
root.get = function(endpoint, successCallback, errorCallback) {
|
|
$http(_get(endpoint)).then(function(data) {
|
|
successCallback(data);
|
|
}, function(data) {
|
|
errorCallback(data);
|
|
});
|
|
};
|
|
|
|
root.post = function(endpoint, json, successCallback, errorCallback) {
|
|
appIdentityService.getIdentity(root.getEnvironment().network, function(err, appIdentity) {
|
|
if (err) return errorCallback(err);
|
|
$http(_post(endpoint, json, appIdentity)).then(function(data) {
|
|
successCallback(data);
|
|
}, function(data) {
|
|
errorCallback(data);
|
|
});
|
|
});
|
|
};
|
|
|
|
var checkOtp = function(pairData, cb) {
|
|
if (pairData.otp) {
|
|
var msg = gettextCatalog.getString('Enter Two Factor for your BitPay account');
|
|
popupService.showPrompt(null, msg, null, function(res) {
|
|
cb(res);
|
|
});
|
|
} else {
|
|
cb();
|
|
}
|
|
};
|
|
|
|
var setBitpayAccount = function(accountData, cb) {
|
|
var data = JSON.stringify(accountData);
|
|
storageService.setBitpayAccount(root.getEnvironment().network, data, function(err) {
|
|
if (err) return cb(err);
|
|
return cb();
|
|
});
|
|
};
|
|
|
|
var _get = function(endpoint) {
|
|
return {
|
|
method: 'GET',
|
|
url: BITPAY_API_URL + endpoint,
|
|
headers: {
|
|
'content-type': 'application/json'
|
|
}
|
|
};
|
|
};
|
|
|
|
var _post = function(endpoint, json, appIdentity) {
|
|
var dataToSign = BITPAY_API_URL + endpoint + JSON.stringify(json);
|
|
var signedData = bitauthService.sign(dataToSign, appIdentity.priv);
|
|
|
|
return {
|
|
method: 'POST',
|
|
url: BITPAY_API_URL + endpoint,
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
'x-identity': appIdentity.pub,
|
|
'x-signature': signedData
|
|
},
|
|
data: json
|
|
};
|
|
};
|
|
|
|
var _postAuth = function(endpoint, json, appIdentity) {
|
|
json['params'].signature = bitauthService.sign(JSON.stringify(json.params), appIdentity.priv);
|
|
json['params'].pubkey = appIdentity.pub;
|
|
json['params'] = JSON.stringify(json.params);
|
|
|
|
var ret = {
|
|
method: 'POST',
|
|
url: BITPAY_API_URL + endpoint,
|
|
headers: {
|
|
'content-type': 'application/json'
|
|
},
|
|
data: json
|
|
};
|
|
|
|
$log.debug('post auth:' + JSON.stringify(ret));
|
|
return ret;
|
|
};
|
|
|
|
var _setError = function(msg, e) {
|
|
$log.error(msg);
|
|
var error = (e && e.data && e.data.error) ? e.data.error : msg;
|
|
return error;
|
|
};
|
|
|
|
return root;
|
|
|
|
});
|