UNPKG

@metamask/ethjs-query

Version:

A simple query layer for the Ethereum RPC.

99 lines (92 loc) 4.54 kB
"use strict"; 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); }); }); } }; }