ethjs-query
Version:
A simple query layer for the Ethereum RPC.
166 lines (125 loc) • 6.77 kB
JavaScript
;
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _defineProperty = require('babel-runtime/core-js/object/define-property');
var _defineProperty2 = _interopRequireDefault(_defineProperty);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var format = require('ethjs-format');
var EthRPC = require('ethjs-rpc');
var promiseToCallback = require('promise-to-callback');
module.exports = Eth;
function Eth(provider, options) {
var self = this;
var optionsObject = options || {};
if (!(this instanceof Eth)) {
throw new Error('[ethjs-query] the Eth object requires the "new" flag in order to function normally (i.e. `const eth = new Eth(provider);`).');
}
if (typeof provider !== 'object') {
throw new Error('[ethjs-query] the Eth object requires that the first input \'provider\' must be an object, got \'' + typeof provider + '\' (i.e. \'const eth = new Eth(provider);\')');
}
self.options = (0, _assign2['default'])({
debug: optionsObject.debug || false,
logger: optionsObject.logger || console,
jsonSpace: optionsObject.jsonSpace || 0
});
self.rpc = new EthRPC(provider);
self.setProvider = self.rpc.setProvider;
}
Eth.prototype.log = function log(message) {
var self = this;
if (self.options.debug) self.options.logger.log('[ethjs-query log] ' + message);
};
(0, _keys2['default'])(format.schema.methods).forEach(function (rpcMethodName) {
(0, _defineProperty2['default'])(Eth.prototype, rpcMethodName.replace('eth_', ''), {
enumerable: true,
value: generateFnFor(rpcMethodName, format.schema.methods[rpcMethodName])
});
});
function generateFnFor(rpcMethodName, methodObject) {
return function outputMethod() {
var performCall = function () {
var _ref = (0, _asyncToGenerator3['default'])( /*#__PURE__*/_regenerator2['default'].mark(function _callee() {
var result, methodOutputs, outputError;
return _regenerator2['default'].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!(args.length < methodObject[2])) {
_context.next = 2;
break;
}
throw new Error('[ethjs-query] method \'' + protoMethodName + '\' requires at least ' + methodObject[2] + ' input (format type ' + methodObject[0][0] + '), ' + args.length + ' provided. For more information visit: https://github.com/ethereum/wiki/wiki/JSON-RPC#' + rpcMethodName.toLowerCase());
case 2:
if (!(args.length > methodObject[0].length)) {
_context.next = 4;
break;
}
throw new Error('[ethjs-query] method \'' + protoMethodName + '\' requires at most ' + methodObject[0].length + ' params, ' + args.length + ' provided \'' + (0, _stringify2['default'])(args, null, self.options.jsonSpace) + '\'. For more information visit: https://github.com/ethereum/wiki/wiki/JSON-RPC#' + rpcMethodName.toLowerCase());
case 4:
// set default block
if (methodObject[3] && args.length < methodObject[3]) {
args.push('latest');
}
// format inputs
this.log('attempting method formatting for \'' + protoMethodName + '\' with inputs ' + (0, _stringify2['default'])(args, null, this.options.jsonSpace));
_context.prev = 6;
inputs = format.formatInputs(rpcMethodName, args);
this.log('method formatting success for \'' + protoMethodName + '\' with formatted result: ' + (0, _stringify2['default'])(inputs, null, this.options.jsonSpace));
_context.next = 14;
break;
case 11:
_context.prev = 11;
_context.t0 = _context['catch'](6);
throw new Error('[ethjs-query] while formatting inputs \'' + (0, _stringify2['default'])(args, null, this.options.jsonSpace) + '\' for method \'' + protoMethodName + '\' error: ' + _context.t0);
case 14:
_context.next = 16;
return this.rpc.sendAsync({ method: rpcMethodName, params: inputs });
case 16:
result = _context.sent;
_context.prev = 17;
this.log('attempting method formatting for \'' + protoMethodName + '\' with raw outputs: ' + (0, _stringify2['default'])(result, null, this.options.jsonSpace));
methodOutputs = format.formatOutputs(rpcMethodName, result);
this.log('method formatting success for \'' + protoMethodName + '\' formatted result: ' + (0, _stringify2['default'])(methodOutputs, null, this.options.jsonSpace));
return _context.abrupt('return', methodOutputs);
case 24:
_context.prev = 24;
_context.t1 = _context['catch'](17);
outputError = new Error('[ethjs-query] while formatting outputs from RPC \'' + (0, _stringify2['default'])(result, null, this.options.jsonSpace) + '\' for method \'' + protoMethodName + '\' ' + _context.t1);
throw outputError;
case 28:
case 'end':
return _context.stop();
}
}
}, _callee, this, [[6, 11], [17, 24]]);
}));
return function performCall() {
return _ref.apply(this, arguments);
};
}();
var callback = null; // eslint-disable-line
var inputs = null; // eslint-disable-line
var inputError = null; // eslint-disable-line
var self = this;
var args = [].slice.call(arguments); // eslint-disable-line
var protoMethodName = rpcMethodName.replace('eth_', ''); // eslint-disable-line
if (args.length > 0 && typeof args[args.length - 1] === 'function') {
callback = args.pop();
}
var promise = performCall.call(this);
// if callback provided, convert promise to callback
if (callback) {
return promiseToCallback(promise)(callback);
}
// only return promise if no callback provided
return promise;
};
}