UNPKG

inventoreminus

Version:

Easily create a web3 provider from scratch.

1,355 lines (1,335 loc) 47.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var _classCallCheck = _interopDefault(require('@babel/runtime/helpers/classCallCheck')); var _createClass = _interopDefault(require('@babel/runtime/helpers/createClass')); var websocket = require('websocket'); var xhr2Cookies = require('xhr2-cookies'); var URL = _interopDefault(require('url-parse')); var _typeof = _interopDefault(require('@babel/runtime/helpers/typeof')); var isFunction = _interopDefault(require('lodash/isFunction')); var isObject = _interopDefault(require('lodash/isObject')); var _possibleConstructorReturn = _interopDefault(require('@babel/runtime/helpers/possibleConstructorReturn')); var _getPrototypeOf = _interopDefault(require('@babel/runtime/helpers/getPrototypeOf')); var _get = _interopDefault(require('@babel/runtime/helpers/get')); var _inherits = _interopDefault(require('@babel/runtime/helpers/inherits')); var _regeneratorRuntime = _interopDefault(require('@babel/runtime/regenerator')); var _asyncToGenerator = _interopDefault(require('@babel/runtime/helpers/asyncToGenerator')); var EventEmitter = _interopDefault(require('eventemitter3')); var isArray = _interopDefault(require('lodash/isArray')); var http = _interopDefault(require('http')); var https = _interopDefault(require('https')); var global = function () { return this || (typeof self === "undefined" ? "undefined" : _typeof(self)) === 'object' && self; }() || new Function('return this')(); var ProviderResolver = function () { function ProviderResolver(providersModuleFactory) { _classCallCheck(this, ProviderResolver); this.providersModuleFactory = providersModuleFactory; } _createClass(ProviderResolver, [{ key: "resolve", value: function resolve(provider, net) { if (!provider) { return provider; } if (typeof provider === 'string') { if (/^http(s)?:\/\//i.test(provider)) { return this.providersModuleFactory.createHttpProvider(provider); } if (/^ws(s)?:\/\//i.test(provider)) { return this.providersModuleFactory.createWebsocketProvider(provider); } if (provider && isObject(net) && isFunction(net.connect)) { return this.providersModuleFactory.createIpcProvider(provider, net); } } if (provider.sendPayload && provider.subscribe) { return provider; } if (typeof global.mist !== 'undefined' && provider.constructor.name === 'EthereumProvider') { return this.providersModuleFactory.createMistEthereumProvider(provider); } if (provider.isEIP1193) { return this.providersModuleFactory.createWeb3EthereumProvider(provider); } if (this.isMetamaskInpageProvider(provider)) { return this.providersModuleFactory.createMetamaskProvider(provider); } return this.providersModuleFactory.createCustomProvider(provider); } }, { key: "isMetamaskInpageProvider", value: function isMetamaskInpageProvider(provider) { return provider.constructor.name === 'MetamaskInpageProvider'; } }]); return ProviderResolver; }(); var messageId = 0; var JsonRpcMapper = function () { function JsonRpcMapper() { _classCallCheck(this, JsonRpcMapper); } _createClass(JsonRpcMapper, null, [{ key: "toPayload", value: function toPayload(method, params) { if (!method) { throw new Error("JSONRPC method should be specified for params: \"".concat(JSON.stringify(params), "\"!")); } var id = messageId; messageId++; return { jsonrpc: '2.0', id: id, method: method, params: params || [] }; } }]); return JsonRpcMapper; }(); var JsonRpcResponseValidator = function () { function JsonRpcResponseValidator() { _classCallCheck(this, JsonRpcResponseValidator); } _createClass(JsonRpcResponseValidator, null, [{ key: "validate", value: function validate(response) { var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (isObject(response)) { if (response.error) { if (response.error instanceof Error) { return new Error("Node error: ".concat(response.error.message)); } return new Error("Node error: ".concat(JSON.stringify(response.error))); } if (payload && response.id !== payload.id) { return new Error("Validation error: Invalid JSON-RPC response ID (request: ".concat(payload.id, " / response: ").concat(response.id, ")")); } if (response.result === undefined) { return new Error('Validation error: Undefined JSON-RPC result'); } return true; } return new Error('Validation error: Response should be of type Object'); } }]); return JsonRpcResponseValidator; }(); var AbstractSocketProvider = function (_EventEmitter) { _inherits(AbstractSocketProvider, _EventEmitter); function AbstractSocketProvider(connection, timeout) { var _this; _classCallCheck(this, AbstractSocketProvider); _this = _possibleConstructorReturn(this, _getPrototypeOf(AbstractSocketProvider).call(this)); _this.connection = connection; _this.timeout = timeout; _this.subscriptions = {}; _this.registerEventListeners(); _this.READY = 'ready'; _this.CONNECT = 'connect'; _this.ERROR = 'error'; _this.CLOSE = 'close'; _this.SOCKET_MESSAGE = 'socket_message'; _this.SOCKET_READY = 'socket_ready'; _this.SOCKET_CLOSE = 'socket_close'; _this.SOCKET_ERROR = 'socket_error'; _this.SOCKET_CONNECT = 'socket_connect'; _this.SOCKET_NETWORK_CHANGED = 'socket_networkChanged'; _this.SOCKET_ACCOUNTS_CHANGED = 'socket_accountsChanged'; return _this; } _createClass(AbstractSocketProvider, [{ key: "supportsSubscriptions", value: function supportsSubscriptions() { return true; } }, { key: "registerEventListeners", value: function registerEventListeners() {} }, { key: "removeAllSocketListeners", value: function removeAllSocketListeners() { this.removeAllListeners(this.SOCKET_MESSAGE); this.removeAllListeners(this.SOCKET_READY); this.removeAllListeners(this.SOCKET_CLOSE); this.removeAllListeners(this.SOCKET_ERROR); this.removeAllListeners(this.SOCKET_CONNECT); } }, { key: "disconnect", value: function disconnect(code, reason) {} }, { key: "send", value: function () { var _send = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(method, parameters) { var response, validationResult; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return this.sendPayload(JsonRpcMapper.toPayload(method, parameters)); case 2: response = _context.sent; validationResult = JsonRpcResponseValidator.validate(response); if (!(validationResult instanceof Error)) { _context.next = 6; break; } throw validationResult; case 6: return _context.abrupt("return", response.result); case 7: case "end": return _context.stop(); } } }, _callee, this); })); function send(_x, _x2) { return _send.apply(this, arguments); } return send; }() }, { key: "sendBatch", value: function sendBatch(methods, moduleInstance) { var payload = []; methods.forEach(function (method) { method.beforeExecution(moduleInstance); payload.push(JsonRpcMapper.toPayload(method.rpcMethod, method.parameters)); }); return this.sendPayload(payload); } }, { key: "onReady", value: function onReady(event) { this.emit(this.READY, event); this.emit(this.SOCKET_READY, event); } }, { key: "onError", value: function onError(error) { this.emit(this.ERROR, error); this.emit(this.SOCKET_ERROR, error); this.removeAllSocketListeners(); this.removeAllListeners(); } }, { key: "onClose", value: function onClose() { var error = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; this.emit(this.CLOSE, error); this.emit(this.SOCKET_CLOSE, error); this.removeAllSocketListeners(); this.removeAllListeners(); } }, { key: "onConnect", value: function () { var _onConnect = _asyncToGenerator( _regeneratorRuntime.mark(function _callee2() { var subscriptionKeys, subscriptionId, _i, _subscriptionKeys, key; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: subscriptionKeys = Object.keys(this.subscriptions); if (!(subscriptionKeys.length > 0)) { _context2.next = 13; break; } _i = 0, _subscriptionKeys = subscriptionKeys; case 3: if (!(_i < _subscriptionKeys.length)) { _context2.next = 13; break; } key = _subscriptionKeys[_i]; _context2.next = 7; return this.subscribe(this.subscriptions[key].subscribeMethod, this.subscriptions[key].parameters[0], this.subscriptions[key].parameters.slice(1)); case 7: subscriptionId = _context2.sent; delete this.subscriptions[subscriptionId]; this.subscriptions[key].id = subscriptionId; case 10: _i++; _context2.next = 3; break; case 13: this.emit(this.SOCKET_CONNECT); this.emit(this.CONNECT); case 15: case "end": return _context2.stop(); } } }, _callee2, this); })); function onConnect() { return _onConnect.apply(this, arguments); } return onConnect; }() }, { key: "onMessage", value: function onMessage(response) { var event; if (!isObject(response)) { response = JSON.parse(response); } if (isArray(response)) { event = response[0].id; } else if (typeof response.id === 'undefined') { event = this.getSubscriptionEvent(response.params.subscription); response = response.params; } else { event = response.id; } this.emit(this.SOCKET_MESSAGE, response); this.emit(event, response); } }, { key: "reset", value: function reset() { this.removeAllListeners(); this.registerEventListeners(); } }, { key: "subscribe", value: function subscribe() { var _this2 = this; var subscribeMethod = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'eth_subscribe'; var subscriptionMethod = arguments.length > 1 ? arguments[1] : undefined; var parameters = arguments.length > 2 ? arguments[2] : undefined; parameters.unshift(subscriptionMethod); return this.send(subscribeMethod, parameters).then(function (subscriptionId) { _this2.subscriptions[subscriptionId] = { id: subscriptionId, subscribeMethod: subscribeMethod, parameters: parameters }; return subscriptionId; }).catch(function (error) { throw new Error("Provider error: ".concat(error)); }); } }, { key: "unsubscribe", value: function unsubscribe(subscriptionId) { var _this3 = this; var unsubscribeMethod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'eth_unsubscribe'; if (this.hasSubscription(subscriptionId)) { return this.send(unsubscribeMethod, [subscriptionId]).then(function (response) { if (response) { _this3.removeAllListeners(_this3.getSubscriptionEvent(subscriptionId)); delete _this3.subscriptions[subscriptionId]; } return response; }); } return Promise.reject(new Error("Provider error: Subscription with ID ".concat(subscriptionId, " does not exist."))); } }, { key: "clearSubscriptions", value: function clearSubscriptions() { var _this4 = this; var unsubscribeMethod = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'eth_unsubscribe'; var unsubscribePromises = []; Object.keys(this.subscriptions).forEach(function (key) { _this4.removeAllListeners(key); unsubscribePromises.push(_this4.unsubscribe(_this4.subscriptions[key].id, unsubscribeMethod)); }); return Promise.all(unsubscribePromises).then(function (results) { if (results.includes(false)) { throw new Error("Could not unsubscribe all subscriptions: ".concat(JSON.stringify(results))); } return true; }); } }, { key: "hasSubscription", value: function hasSubscription(subscriptionId) { return typeof this.getSubscriptionEvent(subscriptionId) !== 'undefined'; } }, { key: "getSubscriptionEvent", value: function getSubscriptionEvent(subscriptionId) { var _this5 = this; if (this.subscriptions[subscriptionId]) { return subscriptionId; } var event; Object.keys(this.subscriptions).forEach(function (key) { if (_this5.subscriptions[key].id === subscriptionId) { event = key; } }); return event; } }, { key: "connected", get: function get() {} }]); return AbstractSocketProvider; }(EventEmitter); var WebsocketProvider = function (_AbstractSocketProvid) { _inherits(WebsocketProvider, _AbstractSocketProvid); function WebsocketProvider(connection, timeout) { var _this; _classCallCheck(this, WebsocketProvider); _this = _possibleConstructorReturn(this, _getPrototypeOf(WebsocketProvider).call(this, connection, timeout)); _this.host = _this.connection.url; return _this; } _createClass(WebsocketProvider, [{ key: "onMessage", value: function onMessage(messageEvent) { _get(_getPrototypeOf(WebsocketProvider.prototype), "onMessage", this).call(this, messageEvent.data); } }, { key: "onError", value: function onError(event) { if (event.code === 'ECONNREFUSED') { this.reconnect(); return; } _get(_getPrototypeOf(WebsocketProvider.prototype), "onError", this).call(this, event); } }, { key: "onClose", value: function onClose(closeEvent) { if (closeEvent.code !== 1000 || closeEvent.wasClean === false) { this.reconnect(); return; } _get(_getPrototypeOf(WebsocketProvider.prototype), "onClose", this).call(this); } }, { key: "reconnect", value: function reconnect() { var _this2 = this; setTimeout(function () { _this2.removeAllSocketListeners(); var connection = []; if (_this2.connection.constructor.name === 'W3CWebsocket') { connection = new _this2.connection.constructor(_this2.host, _this2.connection._client.protocol, null, _this2.connection._client.headers, _this2.connection._client.requestOptions, _this2.connection._client.config); } else { connection = new _this2.connection.constructor(_this2.host, _this2.connection.protocol || undefined); } _this2.connection = connection; _this2.registerEventListeners(); }, 5000); } }, { key: "disconnect", value: function disconnect() { var code = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; this.connection.close(code, reason); } }, { key: "registerEventListeners", value: function registerEventListeners() { this.connection.addEventListener('message', this.onMessage.bind(this)); this.connection.addEventListener('open', this.onReady.bind(this)); this.connection.addEventListener('open', this.onConnect.bind(this)); this.connection.addEventListener('close', this.onClose.bind(this)); this.connection.addEventListener('error', this.onError.bind(this)); } }, { key: "removeAllListeners", value: function removeAllListeners(event) { switch (event) { case this.SOCKET_MESSAGE: this.connection.removeEventListener('message', this.onMessage); break; case this.SOCKET_READY: this.connection.removeEventListener('open', this.onReady); break; case this.SOCKET_CLOSE: this.connection.removeEventListener('close', this.onClose); break; case this.SOCKET_ERROR: this.connection.removeEventListener('error', this.onError); break; case this.SOCKET_CONNECT: this.connection.removeEventListener('connect', this.onConnect); break; } _get(_getPrototypeOf(WebsocketProvider.prototype), "removeAllListeners", this).call(this, event); } }, { key: "isConnecting", value: function isConnecting() { return this.connection.readyState === this.connection.CONNECTING; } }, { key: "sendPayload", value: function sendPayload(payload) { var _this3 = this; return new Promise(function (resolve, reject) { _this3.once('error', reject); if (!_this3.isConnecting()) { var timeout, id; if (_this3.connection.readyState !== _this3.connection.OPEN) { return reject(new Error('Connection error: Connection is not open on send()')); } try { _this3.connection.send(JSON.stringify(payload)); } catch (error) { reject(error); } if (_this3.timeout) { timeout = setTimeout(function () { reject(new Error('Connection error: Timeout exceeded')); }, _this3.timeout); } if (isArray(payload)) { id = payload[0].id; } else { id = payload.id; } _this3.once(id, function (response) { if (timeout) { clearTimeout(timeout); } return resolve(response); }); return; } _this3.once('connect', function () { _this3.sendPayload(payload).then(resolve).catch(reject); }); }); } }, { key: "connected", get: function get() { return this.connection.readyState === this.connection.OPEN; } }]); return WebsocketProvider; }(AbstractSocketProvider); var IpcProvider = function (_AbstractSocketProvid) { _inherits(IpcProvider, _AbstractSocketProvid); function IpcProvider(connection, path) { var _this; _classCallCheck(this, IpcProvider); _this = _possibleConstructorReturn(this, _getPrototypeOf(IpcProvider).call(this, connection, null)); _this.host = path; _this.lastChunk = ''; return _this; } _createClass(IpcProvider, [{ key: "disconnect", value: function disconnect() { this.connection.destroy(); } }, { key: "reconnect", value: function reconnect() { this.connection.connect({ path: this.path }); } }, { key: "onMessage", value: function onMessage(message) { var _this2 = this; var result = null; var returnValues = []; var dechunkedData = message.toString().replace(/\}[\n\r]?\{/g, '}|--|{') .replace(/\}\][\n\r]?\[\{/g, '}]|--|[{') .replace(/\}[\n\r]?\[\{/g, '}|--|[{') .replace(/\}\][\n\r]?\{/g, '}]|--|{') .split('|--|'); dechunkedData.forEach(function (data) { result = null; if (_this2.lastChunk) { data = _this2.lastChunk + data; } try { result = JSON.parse(data); } catch (error) { _this2.lastChunk = data; return; } _this2.lastChunk = null; returnValues.push(result); }); returnValues.forEach(function (chunk) { _get(_getPrototypeOf(IpcProvider.prototype), "onMessage", _this2).call(_this2, chunk); }); } }, { key: "registerEventListeners", value: function registerEventListeners() { this.connection.on('data', this.onMessage.bind(this)); this.connection.on('connect', this.onConnect.bind(this)); this.connection.on('error', this.onError.bind(this)); this.connection.on('close', this.onClose.bind(this)); this.connection.on('timeout', this.onClose.bind(this)); this.connection.on('ready', this.onReady.bind(this)); } }, { key: "removeAllListeners", value: function removeAllListeners(event) { switch (event) { case this.SOCKET_MESSAGE: this.connection.removeListener('data', this.onMessage); break; case this.SOCKET_READY: this.connection.removeListener('ready', this.onReady); break; case this.SOCKET_CLOSE: this.connection.removeListener('close', this.onClose); break; case this.SOCKET_ERROR: this.connection.removeListener('error', this.onError); break; case this.SOCKET_CONNECT: this.connection.removeListener('connect', this.onConnect); break; } _get(_getPrototypeOf(IpcProvider.prototype), "removeAllListeners", this).call(this, event); } }, { key: "sendPayload", value: function sendPayload(payload) { var _this3 = this; return new Promise(function (resolve, reject) { _this3.once('error', reject); if (!_this3.connection.writable) { _this3.connection.connect({ path: _this3.path }); } if (_this3.connection.write(JSON.stringify(payload))) { var id; if (isArray(payload)) { id = payload[0].id; } else { id = payload.id; } _this3.once(id, resolve); return; } return reject(new Error("Connection error: Couldn't write on the socket with Socket.write(payload)")); }); } }, { key: "connected", get: function get() { return !this.connection.pending; } }]); return IpcProvider; }(AbstractSocketProvider); var HttpProvider = function () { function HttpProvider() { var host = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'http://localhost:8545'; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var providersModuleFactory = arguments.length > 2 ? arguments[2] : undefined; _classCallCheck(this, HttpProvider); this.host = host; this.timeout = options.timeout || 0; this.headers = options.headers; this.withCredentials = options.withCredentials || false; this.connected = true; this.providersModuleFactory = providersModuleFactory; this.agent = {}; var keepAlive = false; if (options.keepAlive === true || options.keepAlive !== false) { keepAlive = true; } if (host.substring(0, 5) === 'https') { this.agent['httpsAgent'] = new https.Agent({ keepAlive: keepAlive }); } else { this.agent['httpAgent'] = new http.Agent({ keepAlive: keepAlive }); } } _createClass(HttpProvider, [{ key: "supportsSubscriptions", value: function supportsSubscriptions() { return false; } }, { key: "subscribe", value: function subscribe() { throw new Error('Subscriptions are not supported with the HttpProvider.'); } }, { key: "unsubscribe", value: function unsubscribe() { throw new Error('Subscriptions are not supported with the HttpProvider.'); } }, { key: "disconnect", value: function disconnect() { return true; } }, { key: "send", value: function () { var _send = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(method, parameters) { var response, validationResult; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return this.sendPayload(JsonRpcMapper.toPayload(method, parameters)); case 2: response = _context.sent; validationResult = JsonRpcResponseValidator.validate(response); if (!(validationResult instanceof Error)) { _context.next = 6; break; } throw validationResult; case 6: return _context.abrupt("return", response.result); case 7: case "end": return _context.stop(); } } }, _callee, this); })); function send(_x, _x2) { return _send.apply(this, arguments); } return send; }() }, { key: "sendBatch", value: function sendBatch(methods, moduleInstance) { var payload = []; methods.forEach(function (method) { method.beforeExecution(moduleInstance); payload.push(JsonRpcMapper.toPayload(method.rpcMethod, method.parameters)); }); return this.sendPayload(payload); } }, { key: "sendPayload", value: function sendPayload(payload) { var _this = this; return new Promise(function (resolve, reject) { var request = _this.providersModuleFactory.createXMLHttpRequest(_this.host, _this.timeout, _this.headers, _this.agent, _this.withCredentials); request.onreadystatechange = function () { if (request.readyState !== 0 && request.readyState !== 1) { _this.connected = true; } if (request.readyState === 4) { if (request.status === 200) { try { return resolve(JSON.parse(request.responseText)); } catch (error) { reject(new Error("Invalid JSON as response: ".concat(request.responseText))); } } if (_this.isInvalidHttpEndpoint(request)) { reject(new Error("Connection refused or URL couldn't be resolved: ".concat(_this.host))); } if (request.status >= 400 && request.status <= 499) { reject(new Error("HttpProvider ERROR: ".concat(request.responseText, " (code: ").concat(request.status, ")"))); } } }; request.ontimeout = function () { _this.connected = false; reject(new Error("Connection error: Timeout exceeded after ".concat(_this.timeout, "ms"))); }; try { request.send(JSON.stringify(payload)); } catch (error) { _this.connected = false; reject(error); } }); } }, { key: "isInvalidHttpEndpoint", value: function isInvalidHttpEndpoint(request) { return request.response === null && request.status === 0; } }]); return HttpProvider; }(); var BatchRequest = function () { function BatchRequest(moduleInstance) { _classCallCheck(this, BatchRequest); this.moduleInstance = moduleInstance; this.methods = []; } _createClass(BatchRequest, [{ key: "add", value: function add(method) { if (!isObject(method) && method) { throw new Error('Please provide a object of type AbstractMethod.'); } this.methods.push(method); } }, { key: "execute", value: function execute() { var _this = this; return this.moduleInstance.currentProvider.sendBatch(this.methods, this.moduleInstance).then(function (response) { var errors = []; _this.methods.forEach(function (method, index) { if (!isArray(response)) { method.callback(new Error("BatchRequest error: Response should be of type Array but is: ".concat(_typeof(response))), null); errors.push("Response should be of type Array but is: ".concat(_typeof(response))); return; } var responseItem = response[index] || null; var validationResult = JsonRpcResponseValidator.validate(responseItem); if (validationResult) { try { var mappedResult = method.afterExecution(responseItem.result); response[index] = mappedResult; method.callback(false, mappedResult); } catch (error) { errors.push(error); method.callback(error, null); } return; } errors.push(validationResult); method.callback(validationResult, null); }); if (errors.length > 0) { throw new Error("BatchRequest error: ".concat(JSON.stringify(errors))); } return { methods: _this.methods, response: response }; }); } }]); return BatchRequest; }(); var Web3EthereumProvider = function (_AbstractSocketProvid) { _inherits(Web3EthereumProvider, _AbstractSocketProvid); function Web3EthereumProvider(connection) { var _this; _classCallCheck(this, Web3EthereumProvider); _this = _possibleConstructorReturn(this, _getPrototypeOf(Web3EthereumProvider).call(this, connection, null)); _this.host = 'Web3EthereumProvider'; return _this; } _createClass(Web3EthereumProvider, [{ key: "registerEventListeners", value: function registerEventListeners() { this.connection.on('notification', this.onMessage.bind(this)); this.connection.on('connect', this.onConnect.bind(this)); this.connection.on('connect', this.onReady.bind(this)); this.connection.on('close', this.onClose.bind(this)); this.connection.on('networkChanged', this.onNetworkChanged.bind(this)); this.connection.on('accountsChanged', this.onAccountsChanged.bind(this)); } }, { key: "removeAllListeners", value: function removeAllListeners(event) { switch (event) { case this.SOCKET_NETWORK_CHANGED: this.connection.removeListener('networkChanged', this.onNetworkChanged); break; case this.SOCKET_ACCOUNTS_CHANGED: this.connection.removeListener('accountsChanged', this.onAccountsChanged); break; case this.SOCKET_MESSAGE: this.connection.removeListener('notification', this.onMessage); break; case this.SOCKET_READY: this.connection.removeListener('connect', this.onReady); break; case this.SOCKET_CLOSE: this.connection.removeListener('close', this.onClose); break; case this.SOCKET_ERROR: this.connection.removeListener('close', this.onError); break; case this.SOCKET_CONNECT: this.connection.removeListener('connect', this.onConnect); break; } _get(_getPrototypeOf(Web3EthereumProvider.prototype), "removeAllListeners", this).call(this, event); } }, { key: "removeAllSocketListeners", value: function removeAllSocketListeners() { this.connection.removeAllListeners(); } }, { key: "onNetworkChanged", value: function onNetworkChanged(networkId) { this.emit('networkChanged', networkId); } }, { key: "onAccountsChanged", value: function onAccountsChanged(accounts) { this.emit('accountsChanged', accounts); } }, { key: "onMessage", value: function onMessage(response) { this.emit(this.getSubscriptionEvent(response.subscription), response); } }, { key: "send", value: function () { var _send = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(method, parameters) { var response, validationResult; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: response = this.connection.send(method, parameters); validationResult = JsonRpcResponseValidator.validate(response); if (!(validationResult instanceof Error)) { _context.next = 4; break; } throw validationResult; case 4: return _context.abrupt("return", response); case 5: case "end": return _context.stop(); } } }, _callee, this); })); function send(_x, _x2) { return _send.apply(this, arguments); } return send; }() }, { key: "sendBatch", value: function sendBatch(methods, moduleInstance) { var _this2 = this; var methodCalls = []; methods.forEach(function (method) { method.beforeExecution(moduleInstance); methodCalls.push(_this2.connection.send(method.rpcMethod, method.parameters)); }); return Promise.all(methodCalls); } }]); return Web3EthereumProvider; }(AbstractSocketProvider); var MetamaskProvider = function (_AbstractSocketProvid) { _inherits(MetamaskProvider, _AbstractSocketProvid); function MetamaskProvider(inpageProvider) { var _this; _classCallCheck(this, MetamaskProvider); _this = _possibleConstructorReturn(this, _getPrototypeOf(MetamaskProvider).call(this, inpageProvider, null)); _this.host = 'metamask'; return _this; } _createClass(MetamaskProvider, [{ key: "registerEventListeners", value: function registerEventListeners() { this.connection.on('accountsChanged', this.onAccountsChanged.bind(this)); this.connection.on('networkChanged', this.onReady.bind(this)); this.connection.on('networkChanged', this.onNetworkChanged.bind(this)); this.connection.on('data', this.onMessage.bind(this)); this.connection.on('error', this.onError.bind(this)); } }, { key: "onMessage", value: function onMessage(metamaskParam, payload) { _get(_getPrototypeOf(MetamaskProvider.prototype), "onMessage", this).call(this, payload); } }, { key: "removeAllListeners", value: function removeAllListeners(event) { switch (event) { case this.SOCKET_NETWORK_CHANGED: this.connection.removeListener('networkChanged', this.onNetworkChanged); break; case this.SOCKET_ACCOUNTS_CHANGED: this.connection.removeListener('accountsChanged', this.onAccountsChanged); break; case this.SOCKET_MESSAGE: this.connection.removeListener('data', this.onMessage); break; case this.SOCKET_ERROR: this.connection.removeListener('error', this.onError); break; } _get(_getPrototypeOf(MetamaskProvider.prototype), "removeAllListeners", this).call(this, event); } }, { key: "removeAllSocketListeners", value: function removeAllSocketListeners() { this.connection.removeListener(this.SOCKET_NETWORK_CHANGED, this.onNetworkChanged); this.connection.removeListener(this.SOCKET_ACCOUNTS_CHANGED, this.onAccountsChanged); _get(_getPrototypeOf(MetamaskProvider.prototype), "removeAllSocketListeners", this).call(this); } }, { key: "onNetworkChanged", value: function onNetworkChanged(networkId) { this.emit('networkChanged', networkId); } }, { key: "onAccountsChanged", value: function onAccountsChanged(accounts) { this.emit('accountsChanged', accounts); } }, { key: "disconnect", value: function disconnect() { return true; } }, { key: "sendPayload", value: function sendPayload(payload) { var _this2 = this; return new Promise(function (resolve, reject) { _this2.connection.send(payload, function (error, response) { _this2.removeAllListeners(payload.id); if (!error) { return resolve(response); } reject(error); }); }); } }, { key: "connected", get: function get() { return this.connection.isConnected(); } }]); return MetamaskProvider; }(AbstractSocketProvider); var MistEthereumProvider = function (_AbstractSocketProvid) { _inherits(MistEthereumProvider, _AbstractSocketProvid); function MistEthereumProvider(connection) { var _this; _classCallCheck(this, MistEthereumProvider); _this = _possibleConstructorReturn(this, _getPrototypeOf(MistEthereumProvider).call(this, connection, null)); _this.host = 'mist'; return _this; } _createClass(MistEthereumProvider, [{ key: "registerEventListeners", value: function registerEventListeners() { this.connection.on('data', this.onMessage.bind(this)); this.connection.on('error', this.onError.bind(this)); this.connection.on('connect', this.onConnect.bind(this)); this.connection.on('connect', this.onReady.bind(this)); this.connection.on('end', this.onClose.bind(this)); } }, { key: "removeAllListeners", value: function removeAllListeners(event) { switch (event) { case this.SOCKET_MESSAGE: this.connection.removeListener('data', this.onMessage); break; case this.SOCKET_ERROR: this.connection.removeListener('error', this.onError); break; case this.SOCKET_CONNECT: this.connection.removeListener('connect', this.onConnect); break; case this.SOCKET_READY: this.connection.removeListener('connect', this.onConnect); break; case this.SOCKET_CLOSE: this.connection.removeListener('end', this.onClose); break; } _get(_getPrototypeOf(MistEthereumProvider.prototype), "removeAllListeners", this).call(this, event); } }, { key: "disconnect", value: function disconnect() { return true; } }, { key: "sendPayload", value: function sendPayload(payload) { var _this2 = this; return new Promise(function (resolve, reject) { _this2.connection.send(payload, function (error, response) { _this2.removeAllListeners(payload.id); if (!error) { return resolve(response); } reject(error); }); }); } }, { key: "connected", get: function get() { return this.connection.isConnected(); } }]); return MistEthereumProvider; }(AbstractSocketProvider); var CustomProvider = function () { function CustomProvider(connection) { _classCallCheck(this, CustomProvider); this.host = 'CustomProvider'; this.connection = connection; this.checkConnectionMethods(); } _createClass(CustomProvider, [{ key: "supportsSubscriptions", value: function supportsSubscriptions() { return false; } }, { key: "checkConnectionMethods", value: function checkConnectionMethods() { if (this.connection.send || this.connection.sendAsync) { return true; } throw new Error('Invalid provider injected!'); } }, { key: "subscribe", value: function subscribe() { throw new Error('Subscriptions are not supported with the CustomProvider.'); } }, { key: "unsubscribe", value: function unsubscribe() { throw new Error('Subscriptions are not supported with the CustomProvider.'); } }, { key: "send", value: function () { var _send = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(method, parameters) { var response, validationResult; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return this.sendPayload(JsonRpcMapper.toPayload(method, parameters)); case 2: response = _context.sent; validationResult = JsonRpcResponseValidator.validate(response); if (!(validationResult instanceof Error)) { _context.next = 6; break; } throw validationResult; case 6: return _context.abrupt("return", response.result); case 7: case "end": return _context.stop(); } } }, _callee, this); })); function send(_x, _x2) { return _send.apply(this, arguments); } return send; }() }, { key: "sendBatch", value: function sendBatch(methods, moduleInstance) { var payload = []; methods.forEach(function (method) { method.beforeExecution(moduleInstance); payload.push(JsonRpcMapper.toPayload(method.rpcMethod, method.parameters)); }); return this.sendPayload(payload); } }, { key: "sendPayload", value: function sendPayload(payload) { var _this = this; return new Promise(function (resolve, reject) { if (_this.connection.sendAsync) { _this.connection.sendAsync(payload, function (error, response) { if (!error) { resolve(response); } reject(error); }); return; } _this.connection.send(payload, function (error, response) { if (!error) { resolve(response); } reject(error); }); }); } }]); return CustomProvider; }(); var ProvidersModuleFactory = function () { function ProvidersModuleFactory() { _classCallCheck(this, ProvidersModuleFactory); } _createClass(ProvidersModuleFactory, [{ key: "createBatchRequest", value: function createBatchRequest(moduleInstance) { return new BatchRequest(moduleInstance); } }, { key: "createProviderResolver", value: function createProviderResolver() { return new ProviderResolver(this); } }, { key: "createHttpProvider", value: function createHttpProvider(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new HttpProvider(url, options, this); } }, { key: "createXMLHttpRequest", value: function createXMLHttpRequest(host, timeout, headers, agent, withCredentials) { var request; if (typeof process !== 'undefined' && process.versions != null && process.versions.node != null) { request = new xhr2Cookies.XMLHttpRequest(); request.nodejsSet(agent); } else { request = new XMLHttpRequest(); } request.open('POST', host, true); request.setRequestHeader('Content-Type', 'application/json'); request.timeout = timeout; request.withCredentials = withCredentials; if (headers) { headers.forEach(function (header) { request.setRequestHeader(header.name, header.value); }); } return request; } }, { key: "createWebsocketProvider", value: function createWebsocketProvider(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var connection = ''; if (typeof process !== 'undefined' && process.versions != null && process.versions.node != null) { var headers = options.headers || {}; var urlObject = new URL(url); if (!headers.authorization && urlObject.username && urlObject.password) { var authToken = Buffer.from("".concat(urlObject.username, ":").concat(urlObject.password)).toString('base64'); headers.authorization = "Basic ".concat(authToken); } connection = new websocket.w3cwebsocket(url, options.protocol, null, headers, null, options.clientConfig); } else { connection = new window.WebSocket(url, options.protocol); } return new WebsocketProvider(connection, options.timeout); } }, { key: "createIpcProvider", value: function createIpcProvider(path, net) { return new IpcProvider(net.connect({ path: path }), path); } }, { key: "createWeb3EthereumProvider", value: function createWeb3EthereumProvider(connection) { return new Web3EthereumProvider(connection); } }, { key: "createMetamaskProvider", value: function createMetamaskProvider(inpageProvider) { return new MetamaskProvider(inpageProvider); } }, { key: "createMistEthereumProvider", value: function createMistEthereumProvider(mistEthereumProvider) { return new MistEthereumProvider(mistEthereumProvider); } }, { key: "createCustomProvider", value: function createCustomProvider(connection) { return new CustomProvider(connection); } }]); return ProvidersModuleFactory; }(); var global$1 = function () { return this || (typeof self === "undefined" ? "undefined" : _typeof(self)) === 'object' && self; }() || new Function('return this')(); var ProviderDetector = function () { function ProviderDetector() { _classCallCheck(this, ProviderDetector); } _createClass(ProviderDetector, null, [{ key: "detect", value: function detect() { if (typeof global$1.ethereumProvider !== 'undefined' && global$1.ethereumProvider.constructor.name === 'EthereumProvider') { return global$1.ethereumProvider; } if (typeof global$1.web3 !== 'undefined' && global$1.web3.currentProvider) { return global$1.web3.currentProvider; } return null; } }]); return ProviderDetector; }(); function HttpProvider$1(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new ProvidersModuleFactory().createHttpProvider(url, options); } function WebsocketProvider$1(url) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new ProvidersModuleFactory().createWebsocketProvider(url, options); } function IpcProvider$1(path, net) { return new ProvidersModuleFactory().createIpcProvider(path, net); } function BatchRequest$1(moduleInstance) { return new ProvidersModuleFactory().createBatchRequest(moduleInstance); } function ProviderResolver$1() { return new ProvidersModuleFactory().createProviderResolver(); } exports.BatchRequest = BatchRequest$1; exports.HttpProvider = HttpProvider$1; exports.IpcProvider = IpcProvider$1; exports.ProviderDetector = ProviderDetector; exports.ProviderResolver = ProviderResolver$1; exports.ProvidersModuleFactory = ProvidersModuleFactory; exports.Web3EthereumProvider = Web3EthereumProvider; exports.WebsocketProvider = WebsocketProvider$1;