@bpanel/bpanel-utils
Version:
Utilities for bpanel
410 lines (336 loc) • 11.7 kB
JavaScript
/*!
* clients.js - client extensions of bclient to connect to bpanel app server
* Copyright (c) 2018, Bcoin Devs (MIT License).
* https://github.com/bcoin-org/bpanel-utils
*/
'use strict';
exports.__esModule = true;
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _bclient = require('bclient');
var _bclient2 = _interopRequireDefault(_bclient);
var _hsClient = require('hs-client');
var _hsClient2 = _interopRequireDefault(_hsClient);
var _bcurl = require('bcurl');
var _bsert = require('bsert');
var _bsert2 = _interopRequireDefault(_bsert);
var _bmultisig = require('bmultisig');
var _chain = require('./chain');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var BNodeClient = _bclient2.default.NodeClient,
BWalletClient = _bclient2.default.WalletClient;
var HNodeClient = _hsClient2.default.NodeClient,
HWalletClient = _hsClient2.default.WalletClient;
class BPClient extends _bcurl.Client {
/**
* Create a client for use in bPanel.
* @constructor
* @param {Object} options
* @param {string} [options.path] - base path
* @param {string} options.id - id of node client will be querying
* @param {chain} options.chain - one of 'bitcoin', 'bitcoincash',
* or 'handshake'. Will assume 'bitcoin' if not set
* @param {NodeClient} [node] - can optionally pass a node client
* @param {WalletClient} [wallet] - can optionally pass a wallet client
* @param {MultisigClient} [multisig] - can optionally pass a multisig client
* @returns {BPClient}
*/
constructor(options) {
super(options);
var opts = new ClientOptions(options);
// keep ref to pass to generated clients
this.options = (0, _extends3.default)({}, options, opts);
this.path = opts.path;
this.id = opts.id;
this.chain = opts.chain;
this.node = opts.node;
this.wallet = opts.wallet;
this.multisig = opts.multisig;
// supported client types
this.types = ['node', 'wallet', 'multisig'];
this.init();
}
init() {
var _this = this;
return (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!_this.id) {
_context.next = 6;
break;
}
_this.setNodeClient();
_this.setWalletClient();
_this.setMultisigClient();
_context.next = 6;
return _this.setSPV();
case 6:
return _context.abrupt('return', _this);
case 7:
case 'end':
return _context.stop();
}
}
}, _callee, _this);
}))();
}
/*
* Reset the class with new options
* since the base options start as null
* any options that are not explicitly reset
* will be gone.
* @returns {BpanelClient}
*/
reset(options) {
return new this.constructor(options);
}
/*
* Set a new id and chain if necessary
* will update all clients as well
* @param {string} id - id for client
* @param {string} chain - One of 'bitcoin',
* 'bitcoincash', or 'handshake'
* @returns {BPClient}
*/
setClientInfo(id, chain) {
var _this2 = this;
return (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
(0, _bsert2.default)(id && typeof id === 'string');
_this2.id = id;
if (chain) {
(0, _bsert2.default)(typeof chain === 'string');
(0, _bsert2.default)((0, _chain.isChainSupported)(chain), chain + ' is not a supported chain');
_this2.chain = chain;
}
_this2.options.id = _this2.id;
_this2.options.chain = _this2.chain;
_this2.setNodeClient();
_this2.setWalletClient();
_this2.setMultisigClient();
_context2.next = 10;
return _this2.setSPV();
case 10:
_this2.emit('set clients', { id: _this2.id, chain: _this2.chain });
return _context2.abrupt('return', _this2);
case 12:
case 'end':
return _context2.stop();
}
}
}, _callee2, _this2);
}))();
}
/**
* Get an object of all clients available on server
* @returns {Promise}
*/
getClients() {
return this.get('/clients');
}
/**
* Get info for default client on the server
* @returns {Promise}
*/
getDefault() {
return this.get('/clients/default');
}
/**
* Get info from bPanel server about client of this.id
* @param {string} [_id] - id of client you'd like to get
* info for
* @returns {Promise}
*/
getClientInfo(_id) {
var health = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var id = _id ? _id : this.id;
return this.get('/clients/' + id, { health: health });
}
/*
* Get a client for sending requests to a node
* Returns this.node and sets it if none is set
* @returns {Client}
*/
getNodeClient() {
if (!this.node) this.setNodeClient();
return this.node;
}
/*
* Get a client for sending requests to a wallet node
* Returns this.wallet and sets it if none is set
* @returns {Client}
*/
getWalletClient() {
if (!this.wallet) this.setWalletClient();
return this.wallet;
}
/*
* Get a client for sending requests to a multisig node
* Returns this.multisig and sets it if none is set
* @returns {Client}
*/
getMultisigClient() {
if (!this.multisig) this.setMultisigClient();
return this.multisig;
}
/*
* Set the node client for the class
* @param {string} _path - Can set a custom path
* @returns {void}
*/
setNodeClient() {
var _path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var path = _path;
if (!path) {
(0, _bsert2.default)(this.id, 'Must have an id before setting node');
path = this.getClientPaths(this.id).node;
}
var options = (0, _extends3.default)({}, this.options, { path: path });
if (this.chain === 'handshake') this.node = new HNodeClient(options);
// defaults to returning bcoin client
else this.node = new BNodeClient(options);
this.emit('set node', { id: this.id, chain: this.chain });
}
/*
* Set the wallet client for the class
* @param {string} _path - Can set a custom path
* @returns {void}
*/
setWalletClient() {
var _path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var path = _path;
if (!path) {
(0, _bsert2.default)(this.id, 'Must have an id before setting node');
path = this.getClientPaths(this.id).wallet;
}
var options = (0, _extends3.default)({}, this.options, { path: path });
if (this.chain === 'handshake') this.wallet = new HWalletClient(options);
// defaults to returning bcoin client
else this.wallet = new BWalletClient(options);
this.emit('set wallet', { id: this.id, chain: this.chain });
}
/*
* Set the wallet client for the class
* @param {string} _path - Can set a custom path
* @returns {void}
*/
setMultisigClient() {
var _path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var path = _path;
if (!path) {
(0, _bsert2.default)(this.id, 'Must have an id before setting node');
path = this.getClientPaths(this.id).multisig;
}
var options = (0, _extends3.default)({}, this.options, { path: path });
this.multisig = new _bmultisig.Client(options);
this.emit('set multisig', { id: this.id, chain: this.chain });
}
/*
* Get path for the client of a given id. Defaults to this.id
* @param {string} [_id] - pass an id to get paths for another client
* @returns {object} paths - object with client types mapped to endpoint
* in format: `/clients/:id/:type` where type can be 'node',
* 'wallet', or 'multisig'
*/
getClientPaths(_id) {
var id = _id ? _id : this.id;
return this.types.reduce(function (paths, type) {
paths[type] = '/clients/' + id + '/' + type;
return paths;
}, {});
}
/*
* Until bcoin, bcash and hsd return SPV flags in `info` we need to test
*/
setSPV() {
var _this3 = this;
return (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3() {
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.prev = 0;
_context3.next = 3;
return _this3.node.getBlock(0);
case 3:
_this3.isSPV = false;
_context3.next = 9;
break;
case 6:
_context3.prev = 6;
_context3.t0 = _context3['catch'](0);
_this3.isSPV = true;
case 9:
case 'end':
return _context3.stop();
}
}
}, _callee3, _this3, [[0, 6]]);
}))();
}
}
/**
* Client Options
*/
class ClientOptions {
constructor(options) {
this.id = '';
this.path = '';
this.chain = null;
this.node = null;
this.wallet = null;
this.multisig = null;
if (options) this.fromOptions(options);
}
fromOptions(options) {
var id = options.id,
chain = options.chain,
path = options.path,
node = options.node,
wallet = options.wallet,
multisig = options.multisig;
if (id) {
(0, _bsert2.default)(typeof id === 'string');
this.id = id;
}
if (chain) {
(0, _bsert2.default)(typeof chain === 'string');
(0, _bsert2.default)((0, _chain.isChainSupported)(chain), chain + ' is not a supported chain');
this.chain = chain;
}
if (node) {
(0, _bsert2.default)(node instanceof _bcurl.Client);
// want to make sure that the client matches with the chain
if (this.chain === 'bitcoin' || this.chain === 'bitcoincash') (0, _bsert2.default)(node instanceof BNodeClient);
if (this.chain === 'handshake') (0, _bsert2.default)(node instanceof HNodeClient);
this.node = node;
}
if (wallet) {
(0, _bsert2.default)(wallet instanceof _bcurl.Client);
// want to make sure that the client matches with the chain
if (this.chain === 'bitcoin' || this.chain === 'bitcoincash') (0, _bsert2.default)(wallet instanceof BWalletClient);
if (this.chain === 'handshake') (0, _bsert2.default)(wallet instanceof HWalletClient);
this.wallet = wallet;
}
if (multisig) {
(0, _bsert2.default)(multisig instanceof _bmultisig.Client);
this.multisig = multisig;
}
if (path) {
// TODO: add more robust path handling similar to bmultisig client
(0, _bsert2.default)(typeof path === 'string');
this.path = path;
}
return this;
}
}
exports.default = BPClient;