@metamask/ethjs-query
Version:
A simple query layer for the Ethereum RPC.
99 lines (92 loc) • 4.54 kB
JavaScript
var format = require('@metamask/ethjs-format');
var EthRPC = require('@metamask/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 = Object.assign({
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);
};
Object.keys(format.schema.methods).forEach(function (rpcMethodName) {
Object.defineProperty(Eth.prototype, rpcMethodName.replace('eth_', ''), {
enumerable: true,
value: generateFnFor(rpcMethodName, format.schema.methods[rpcMethodName])
});
});
function generateFnFor(rpcMethodName, methodObject) {
return function outputMethod() {
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;
function performCall() {
var _this = this;
return new Promise(function (resolve, reject) {
// validate arg length
if (args.length < methodObject[2]) {
reject(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()));
return;
}
if (args.length > methodObject[0].length) {
reject(new Error("[ethjs-query] method '" + protoMethodName + "' requires at most " + methodObject[0].length + " params, " + args.length + " provided '" + JSON.stringify(args, null, self.options.jsonSpace) + "'. For more information visit: https://github.com/ethereum/wiki/wiki/JSON-RPC#" + rpcMethodName.toLowerCase()));
return;
}
// set default block
if (methodObject[3] && args.length < methodObject[3]) {
args.push('latest');
}
// format inputs
_this.log("attempting method formatting for '" + protoMethodName + "' with inputs " + JSON.stringify(args, null, _this.options.jsonSpace));
try {
inputs = format.formatInputs(rpcMethodName, args);
_this.log("method formatting success for '" + protoMethodName + "' with formatted result: " + JSON.stringify(inputs, null, _this.options.jsonSpace));
} catch (formattingError) {
reject(new Error("[ethjs-query] while formatting inputs '" + JSON.stringify(args, null, _this.options.jsonSpace) + "' for method '" + protoMethodName + "' error: " + formattingError));
return;
}
// perform rpc call
_this.rpc.sendAsync({
method: rpcMethodName,
params: inputs
}).then(function (result) {
// format result
_this.log("attempting method formatting for '" + protoMethodName + "' with raw outputs: " + JSON.stringify(result, null, _this.options.jsonSpace));
var methodOutputs = format.formatOutputs(rpcMethodName, result);
_this.log("method formatting success for '" + protoMethodName + "' formatted result: " + JSON.stringify(methodOutputs, null, _this.options.jsonSpace));
resolve(methodOutputs);
})["catch"](function (error) {
reject(error);
});
});
}
};
}
;