bitcore-wallet-service
Version:
A service for Mutisig HD Bitcoin Wallets
261 lines (223 loc) • 7.69 kB
text/typescript
import * as crypto from 'crypto';
import * as _ from 'lodash';
import * as request from 'request';
import config from '../config';
import { ClientError } from '../lib/errors/clienterror';
import { checkRequired } from '../lib/server';
export class BanxaService {
request: any = request;
private banxaGetKeys(req) {
if (!config.banxa) throw new Error('Banxa missing credentials');
let env: 'sandbox' | 'production' | 'sandboxWeb' | 'productionWeb';
env = req.body.env === 'production' ? 'production' : 'sandbox';
if (req.body.context === 'web') {
env += 'Web';
}
delete req.body.env;
delete req.body.context;
const keys: {
API: string;
API_KEY: string;
SECRET_KEY: string;
} = {
API: config.banxa[env].api,
API_KEY: config.banxa[env].apiKey,
SECRET_KEY: config.banxa[env].secretKey
};
return keys;
}
private getBanxaSignature(method: 'get' | 'post', endpoint: string, apiKey: string, secret: string, body?: string) {
let signature, auth: string
const nonce = Date.now().toString();
switch (method) {
case 'get':
signature = 'GET' + '\n' + `/api${endpoint}` + '\n' + nonce;
break;
case 'post':
const stringifiedBody = body ? JSON.stringify(_.cloneDeep(body)) : '';
signature = 'POST' + '\n' + `/api${endpoint}` + '\n' + nonce + '\n' + stringifiedBody;
break;
default:
signature = undefined;
break;
}
const localSignature = crypto.createHmac('sha256', secret).update(signature).digest('hex');
auth = `${apiKey}:${localSignature}:${nonce}`
return auth;
}
banxaGetCoins(req): Promise<any> {
return new Promise((resolve, reject) => {
const keys = this.banxaGetKeys(req);
const API = keys.API;
const API_KEY = keys.API_KEY;
const SECRET_KEY = keys.SECRET_KEY;
if (!checkRequired(req.body, ['orderType'])) {
return reject(new ClientError("Banxa's request missing arguments"));
}
if (!['buy', 'sell'].includes(req.body.orderType)) {
return reject(new ClientError("Banxa's 'orderType' property must be 'sell' or 'buy'"));
}
const UriPath = `/coins/${req.body.orderType}`;
const URL: string = API + UriPath;
const auth = this.getBanxaSignature('get', UriPath, API_KEY, SECRET_KEY);
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth}`
};
this.request.get(
URL,
{
headers,
json: true
},
(err, data) => {
if (err) {
return reject(err.body ? err.body : err);
} else {
return resolve(data.body ? data.body : data);
}
}
);
});
}
banxaGetPaymentMethods(req): Promise<any> {
return new Promise((resolve, reject) => {
const keys = this.banxaGetKeys(req);
const API = keys.API;
const API_KEY = keys.API_KEY;
const SECRET_KEY = keys.SECRET_KEY;
let qs: string[] = [];
if (req.body.source) qs.push('source=' + req.body.source);
if (req.body.target) qs.push('target=' + req.body.target);
const UriPath = `/payment-methods${qs.length > 0 ? '?' + qs.join('&') : ''}`;
const URL: string = API + UriPath;
const auth = this.getBanxaSignature('get', UriPath, API_KEY, SECRET_KEY);
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth}`
};
this.request.get(
URL,
{
headers,
json: true
},
(err, data) => {
if (err) {
return reject(err.body ? err.body : err);
} else {
return resolve(data.body ? data.body : data);
}
}
);
});
}
banxaGetQuote(req): Promise<any> {
return new Promise((resolve, reject) => {
const keys = this.banxaGetKeys(req);
const API = keys.API;
const API_KEY = keys.API_KEY;
const SECRET_KEY = keys.SECRET_KEY;
if (!checkRequired(req.body, ['source', 'target'])) {
return reject(new ClientError("Banxa's request missing arguments"));
}
let qs: string[] = [];
qs.push('source=' + req.body.source);
qs.push('target=' + req.body.target);
if (req.body.source_amount) qs.push('source_amount=' + req.body.source_amount);
if (req.body.target_amount) qs.push('target_amount=' + req.body.target_amount);
if (req.body.payment_method_id) qs.push('payment_method_id=' + req.body.payment_method_id);
if (req.body.account_reference) qs.push('account_reference=' + req.body.account_reference);
if (req.body.blockchain) qs.push('blockchain=' + req.body.blockchain);
const UriPath = `/prices${qs.length > 0 ? '?' + qs.join('&') : ''}`;
const URL: string = API + UriPath;
const auth = this.getBanxaSignature('get', UriPath, API_KEY, SECRET_KEY);
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth}`
};
this.request.get(
URL,
{
headers,
json: true
},
(err, data) => {
if (err) {
return reject(err.body ? err.body : err);
} else {
return resolve(data.body ? data.body : data);
}
}
);
});
}
banxaCreateOrder(req): Promise<any> {
return new Promise((resolve, reject) => {
const keys = this.banxaGetKeys(req);
const API = keys.API;
const API_KEY = keys.API_KEY;
const SECRET_KEY = keys.SECRET_KEY;
if (!checkRequired(req.body, ['account_reference', 'source', 'target', 'wallet_address', 'return_url_on_success'])) {
return reject(new ClientError("Banxa's request missing arguments"));
}
delete req.body.payment_method_id;
const UriPath = '/orders';
const URL: string = API + UriPath;
const auth = this.getBanxaSignature('post', UriPath, API_KEY, SECRET_KEY, req.body);
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth}`
};
this.request.post(
URL,
{
headers,
body: req.body,
json: true
},
(err, data) => {
if (err) {
return reject(err.body ? err.body : err);
} else {
return resolve(data.body ? data.body : data);
}
}
);
});
}
banxaGetOrder(req): Promise<any> {
return new Promise((resolve, reject) => {
const keys = this.banxaGetKeys(req);
const API = keys.API;
const API_KEY = keys.API_KEY;
const SECRET_KEY = keys.SECRET_KEY;
if (!checkRequired(req.body, ['order_id'])) {
return reject(new ClientError("Banxa's request missing arguments"));
}
let qs: string[] = [];
if (req.body.fx_currency) qs.push('fx_currency=' + req.body.fx_currency);
const UriPath = `/orders/${req.body.order_id}${qs.length > 0 ? '?' + qs.join('&') : ''}`;
const URL: string = API + UriPath;
const auth = this.getBanxaSignature('get', UriPath, API_KEY, SECRET_KEY);
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${auth}`
};
this.request.get(
URL,
{
headers,
json: true
},
(err, data) => {
if (err) {
return reject(err.body ? err.body : err);
} else {
return resolve(data.body ? data.body : data);
}
}
);
});
}
}