UNPKG

ethjs-query

Version:

A simple query layer for the Ethereum RPC.

115 lines (98 loc) 5.08 kB
'use strict'; 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 = 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 try { _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); return; } catch (outputFormattingError) { var outputError = new Error('[ethjs-query] while formatting outputs from RPC \'' + JSON.stringify(result, null, _this.options.jsonSpace) + '\' for method \'' + protoMethodName + '\' ' + outputFormattingError); reject(outputError); return; } })['catch'](function (error) { var outputError = new Error('[ethjs-query] while formatting outputs from RPC \'' + JSON.stringify(error, null, _this.options.jsonSpace) + '\''); reject(outputError); return; }); }); } }; }