@liskhq/lisk-api-client
Version:
An API client for the Lisk network
115 lines • 4.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.IPCChannel = void 0;
const path = require("path");
const os_1 = require("os");
const events_1 = require("events");
const zeromq_1 = require("zeromq");
const utils_1 = require("./utils");
const CONNECTION_TIMEOUT = 5000;
const RESPONSE_TIMEOUT = 10000;
const getSocketsPath = (dataPath) => {
const socketDir = path.join(path.resolve(dataPath.replace('~', (0, os_1.homedir)())), 'tmp', 'sockets');
return {
pub: `ipc://${socketDir}/external.pub.ipc`,
sub: `ipc://${socketDir}/external.sub.ipc`,
rpc: `ipc://${socketDir}/engine.external.rpc.ipc`,
};
};
class IPCChannel {
constructor(dataPath) {
this.isAlive = false;
this._pendingRequests = {};
const socketsDir = getSocketsPath(dataPath);
this._eventPubSocketPath = socketsDir.pub;
this._rpcServerSocketPath = socketsDir.rpc;
this._subSocket = new zeromq_1.Subscriber();
this._rpcClient = new zeromq_1.Dealer();
this._events = new events_1.EventEmitter();
this._id = 0;
}
async connect() {
try {
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('IPC Socket client connection timeout. Please check if IPC server is running.'));
}, CONNECTION_TIMEOUT);
this._subSocket.events.on('connect', () => {
clearTimeout(timeout);
resolve();
});
this._subSocket.events.on('bind:error', reject);
this._subSocket.connect(this._eventPubSocketPath);
});
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('IPC Socket client connection timeout. Please check if IPC server is running.'));
}, CONNECTION_TIMEOUT);
this._rpcClient.events.on('connect', () => {
clearTimeout(timeout);
resolve(undefined);
});
this._rpcClient.events.on('bind:error', reject);
this._rpcClient.connect(this._rpcServerSocketPath);
});
this.isAlive = true;
}
catch (error) {
this._subSocket.close();
this._rpcClient.close();
throw error;
}
this._listenToRPCResponse().catch(() => { });
this._listenToEvents().catch(() => { });
}
async disconnect() {
this._subSocket.close();
this._rpcClient.close();
this.isAlive = false;
}
async invoke(actionName, params) {
this._id += 1;
const action = {
id: this._id,
jsonrpc: '2.0',
method: actionName,
params: params !== null && params !== void 0 ? params : {},
};
await this._rpcClient.send([JSON.stringify(action)]);
const response = (0, utils_1.defer)();
this._pendingRequests[action.id] = response;
return (0, utils_1.promiseWithTimeout)([response.promise], RESPONSE_TIMEOUT, `Response not received in ${RESPONSE_TIMEOUT}ms`);
}
subscribe(eventName, cb) {
this._subSocket.subscribe(eventName);
this._events.on(eventName, cb);
}
unsubscribe(eventName, cb) {
this._subSocket.unsubscribe(eventName);
this._events.off(eventName, cb);
}
async _listenToRPCResponse() {
for await (const [eventData] of this._rpcClient) {
const res = JSON.parse(eventData.toString());
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];
}
}
}
async _listenToEvents() {
this._subSocket.subscribe('invoke');
for await (const [_event, eventData] of this._subSocket) {
const res = JSON.parse(eventData.toString());
this._events.emit(res.method, res.params);
}
}
}
exports.IPCChannel = IPCChannel;
//# sourceMappingURL=ipc_channel.js.map