UNPKG

@liskhq/lisk-api-client

Version:
144 lines 5.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WSChannel = exports.RESPONSE_TIMEOUT = exports.CONNECTION_TIMEOUT = void 0; const WebSocket = require("isomorphic-ws"); const events_1 = require("events"); const utils_1 = require("./utils"); exports.CONNECTION_TIMEOUT = 5000; exports.RESPONSE_TIMEOUT = 10000; class WSChannel { constructor(url) { this.isAlive = false; this._requestCounter = 0; this._pendingRequests = {}; this._url = url; this._emitter = new events_1.EventEmitter(); } async connect() { this._ws = new WebSocket(this._url); this._ws.onclose = this._handleClose.bind(this); this._ws.onmessage = this._handleMessage.bind(this); this._ws.addEventListener('ping', this._handlePing.bind(this)); const connectHandler = new Promise(resolve => { var _a; const onOpen = () => { var _a; this.isAlive = true; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.removeEventListener('open', onOpen); resolve(); }; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.addEventListener('open', onOpen); }); const errorHandler = new Promise((_, reject) => { var _a; const onError = (error) => { var _a; this.isAlive = false; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.removeEventListener('error', onError); reject(error.error); }; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.addEventListener('error', onError); }); try { await (0, utils_1.promiseWithTimeout)([connectHandler, errorHandler], exports.CONNECTION_TIMEOUT, `Could not connect in ${exports.CONNECTION_TIMEOUT}ms`); } catch (err) { this._ws.close(); throw err; } } async disconnect() { this._requestCounter = 0; this._pendingRequests = {}; if (!this._ws) { return; } if (this._ws.readyState === WebSocket.CLOSED) { this.isAlive = false; this._ws = undefined; return; } const closeHandler = new Promise(resolve => { var _a; const onClose = () => { var _a; this.isAlive = false; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.removeEventListener('close', onClose); resolve(); }; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.addEventListener('close', onClose); }); this._ws.close(); await (0, utils_1.promiseWithTimeout)([closeHandler], exports.CONNECTION_TIMEOUT, `Could not disconnect in ${exports.CONNECTION_TIMEOUT}ms`); } async invoke(actionName, params) { var _a; if (!this.isAlive) { throw new Error('Websocket client is not connected.'); } const request = { jsonrpc: '2.0', id: this._requestCounter, method: actionName, params: params !== null && params !== void 0 ? params : {}, }; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(request)); const response = (0, utils_1.defer)(); this._pendingRequests[this._requestCounter] = response; this._requestCounter += 1; return (0, utils_1.promiseWithTimeout)([response.promise], exports.RESPONSE_TIMEOUT, `Response not received in ${exports.RESPONSE_TIMEOUT}ms`); } subscribe(eventName, cb) { var _a; const request = { jsonrpc: '2.0', id: this._requestCounter, method: 'subscribe', params: { topics: [eventName], }, }; this._requestCounter += 1; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(request)); this._emitter.on(eventName, cb); } unsubscribe(eventName) { var _a; const request = { jsonrpc: '2.0', id: this._requestCounter, method: 'unsubscribe', params: { topics: [eventName], }, }; this._requestCounter += 1; (_a = this._ws) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(request)); } _handleClose() { this.isAlive = false; } _handlePing() { this.isAlive = true; } _handleMessage(event) { const res = JSON.parse(event.data); if ((0, utils_1.messageIsNotification)(res)) { this._emitter.emit(res.method, res.params); } else { const id = typeof res.id === 'number' ? res.id : parseInt(res.id, 10); if (this._pendingRequests[id]) { if (res.error) { this._pendingRequests[id].reject((0, utils_1.convertRPCError)(res.error)); } else { this._pendingRequests[id].resolve(res.result); } delete this._pendingRequests[id]; } } } } exports.WSChannel = WSChannel; //# sourceMappingURL=ws_channel.js.map