wehelpjs
Version:
wehelpjs is the JavaScript API Library for the WeYouMe blockchain
383 lines (309 loc) • 9.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _events = _interopRequireDefault(require("events"));
var _bluebird = _interopRequireDefault(require("bluebird"));
var _config = _interopRequireDefault(require("../config"));
var _methods = _interopRequireDefault(require("./methods"));
var _transports = _interopRequireDefault(require("./transports"));
var _utils = require("../utils");
var _ecc = require("../auth/ecc");
var _serializer = require("../auth/serializer");
var _http = require("./transports/http");
var _werpcjs = require("werpcjs");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class Api extends _events.default {
constructor(options = {}) {
super(options);
this._setTransport(options);
this._setLogger(options);
this.options = options;
this.seqNo = 0; // used for rpc calls
_methods.default.forEach(method => {
const methodName = method.method_name || (0, _utils.camelCase)(method.method);
const methodParams = method.params || [];
this[`${methodName}With`] = (options, callback) => {
return this.send(method.api, {
method: method.method,
params: methodParams.map(param => options[param])
}, callback);
};
this[methodName] = (...args) => {
const options = methodParams.reduce((memo, param, i) => {
memo[param] = args[i]; // eslint-disable-line no-param-reassign
return memo;
}, {});
const callback = args[methodParams.length];
return this[`${methodName}With`](options, callback);
};
this[`${methodName}WithAsync`] = _bluebird.default.promisify(this[`${methodName}With`]);
this[`${methodName}Async`] = _bluebird.default.promisify(this[methodName]);
});
this.callAsync = _bluebird.default.promisify(this.call);
this.signedCallAsync = _bluebird.default.promisify(this.signedCall);
}
_setTransport(options) {
if (options.url && options.url.match('^((http|https)?:\/\/)')) {
options.uri = options.url;
options.transport = 'http';
this._transportType = options.transport;
this.options = options;
this.transport = new _transports.default.http(options);
} else if (options.url && options.url.match('^((ws|wss)?:\/\/)')) {
options.websocket = options.url;
options.transport = 'ws';
this._transportType = options.transport;
this.options = options;
this.transport = new _transports.default.ws(options);
} else if (options.transport) {
if (this.transport && this._transportType !== options.transport) {
this.transport.stop();
}
this._transportType = options.transport;
if (typeof options.transport === 'string') {
if (!_transports.default[options.transport]) {
throw new TypeError('Invalid `transport`, valid values are `http`, `ws` or a class');
}
this.transport = new _transports.default[options.transport](options);
} else {
this.transport = new options.transport(options);
}
} else {
this.transport = new _transports.default.ws(options);
}
}
_setLogger(options) {
if (options.hasOwnProperty('logger')) {
switch (typeof options.logger) {
case 'function':
this.__logger = {
log: options.logger
};
break;
case 'object':
if (typeof options.logger.log !== 'function') {
throw new Error('setOptions({logger:{}}) must have a property .log of type function');
}
this.__logger = options.logger;
break;
case 'undefined':
if (this.__logger) break;
default:
this.__logger = false;
}
}
}
log(logLevel) {
if (this.__logger) {
if (arguments.length > 1 && typeof this.__logger[logLevel] === 'function') {
let args = Array.prototype.slice.call(arguments, 1);
this.__logger[logLevel].apply(this.__logger, args);
} else {
this.__logger.log.apply(this.__logger, arguments);
}
}
}
start() {
return this.transport.start();
}
stop() {
return this.transport.stop();
}
send(api, data, callback) {
var cb = callback;
if (this.__logger) {
let id = Math.random();
let self = this;
this.log('xmit:' + id + ':', data);
cb = function (e, d) {
if (e) {
self.log('error', 'rsp:' + id + ':\n\n', e, d);
} else {
self.log('rsp:' + id + ':', d);
}
if (callback) {
callback.apply(self, arguments);
}
};
}
return this.transport.send(api, data, cb);
}
call(method, params, callback) {
if (this._transportType !== 'http') {
callback(new Error('RPC methods can only be called when using http transport'));
return;
}
const id = ++this.seqNo;
(0, _http.jsonRpc)(this.options.uri, {
method,
params,
id
}).then(res => {
callback(null, res);
}, err => {
callback(err);
});
}
signedCall(method, params, account, key, callback) {
if (this._transportType !== 'http') {
callback(new Error('RPC methods can only be called when using http transport'));
return;
}
const id = ++this.seqNo;
let request;
try {
request = (0, _werpcjs.sign)({
method,
params,
id
}, account, [key]);
} catch (error) {
callback(error);
return;
}
(0, _http.jsonRpc)(this.options.uri, request).then(res => {
callback(null, res);
}, err => {
callback(err);
});
}
setOptions(options) {
Object.assign(this.options, options);
this._setLogger(options);
this._setTransport(options);
this.transport.setOptions(options);
}
setWebSocket(url) {
this.setOptions({
websocket: url
});
}
setUri(url) {
this.setOptions({
uri: url
});
}
streamBlockNumber(mode = 'head', callback, ts = 200) {
if (typeof mode === 'function') {
callback = mode;
mode = 'head';
}
let current = '';
let running = true;
const update = () => {
if (!running) return;
this.getDynamicGlobalPropertiesAsync().then(result => {
const blockId = mode === 'irreversible' ? result.last_irreversible_block_num : result.head_block_number;
if (blockId !== current) {
if (current) {
for (let i = current; i < blockId; i++) {
if (i !== current) {
callback(null, i);
}
current = i;
}
} else {
current = blockId;
callback(null, blockId);
}
}
_bluebird.default.delay(ts).then(() => {
update();
});
}, err => {
callback(err);
});
};
update();
return () => {
running = false;
};
}
streamBlock(mode = 'head', callback) {
if (typeof mode === 'function') {
callback = mode;
mode = 'head';
}
let current = '';
let last = '';
const release = this.streamBlockNumber(mode, (err, id) => {
if (err) {
release();
callback(err);
return;
}
current = id;
if (current !== last) {
last = current;
this.getBlock(current, callback);
}
});
return release;
}
streamTransactions(mode = 'head', callback) {
if (typeof mode === 'function') {
callback = mode;
mode = 'head';
}
const release = this.streamBlock(mode, (err, result) => {
if (err) {
release();
callback(err);
return;
}
if (result && result.transactions) {
result.transactions.forEach(transaction => {
callback(null, transaction);
});
}
});
return release;
}
streamOperations(mode = 'head', callback) {
if (typeof mode === 'function') {
callback = mode;
mode = 'head';
}
const release = this.streamTransactions(mode, (err, transaction) => {
if (err) {
release();
callback(err);
return;
}
transaction.operations.forEach(operation => {
callback(null, operation);
});
});
return release;
}
broadcastTransactionSynchronousWith(options, callback) {
const trx = options.trx;
return this.send('network_broadcast_api', {
method: 'broadcast_transaction_synchronous',
params: [trx]
}, (err, result) => {
if (err) {
const {
signed_transaction
} = _serializer.ops; // console.log('-- broadcastTransactionSynchronous -->', JSON.stringify(signed_transaction.toObject(trx), null, 2));
// toObject converts objects into serializable types
const trObject = signed_transaction.toObject(trx);
const buf = signed_transaction.toBuffer(trx);
err.digest = _ecc.hash.sha256(buf).toString('hex');
err.transaction_id = buf.toString('hex');
err.transaction = JSON.stringify(trObject);
callback(err, '');
} else {
callback('', result);
}
});
}
} // Export singleton instance
const api = new Api(_config.default);
exports = module.exports = api;
var _default = api;
exports.default = _default;
exports.Api = Api;
exports.api = Api;