UNPKG

lisk-framework

Version:

Lisk blockchain application platform

152 lines 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ABIClient = void 0; const lisk_codec_1 = require("@liskhq/lisk-codec"); const zeromq_1 = require("zeromq"); const abi_1 = require("../abi"); const DEFAULT_TIMEOUT = 3000; const MAX_UINT64 = BigInt(2) ** BigInt(64) - BigInt(1); const defer = () => { let resolve; let reject; const promise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; }); return { promise, resolve, reject }; }; const timeout = async (ms, message) => new Promise((_, reject) => { const id = setTimeout(() => { clearTimeout(id); reject(new Error(message !== null && message !== void 0 ? message : `Timed out in ${ms}ms.`)); }, ms); }); class ABIClient { constructor(logger, socketPath) { this._pendingRequests = {}; this._globalID = BigInt(0); this._logger = logger; this._socketPath = socketPath; this._dealer = new zeromq_1.Dealer(); } async start() { await new Promise((resolve, reject) => { const connectionTimeout = setTimeout(() => { reject(new Error('IPC Socket client connection timeout. Please check if IPC server is running.')); }, DEFAULT_TIMEOUT); this._dealer.events.on('connect', () => { clearTimeout(connectionTimeout); resolve(undefined); }); this._dealer.events.on('bind:error', reject); this._dealer.connect(this._socketPath); }); this._listenToRPCResponse().catch(err => { this._logger.debug({ err: err }, 'Failed to listen to the ABI response'); }); } stop() { this._dealer.disconnect(this._socketPath); this._pendingRequests = {}; this._globalID = BigInt(0); } async init(req) { return this._call('init', req, abi_1.initRequestSchema, abi_1.initResponseSchema); } async initStateMachine(req) { return this._call('initStateMachine', req, abi_1.initStateMachineRequestSchema, abi_1.initStateMachineResponseSchema); } async initGenesisState(req) { return this._call('initGenesisState', req, abi_1.initGenesisStateRequestSchema, abi_1.initGenesisStateResponseSchema); } async insertAssets(req) { return this._call('insertAssets', req, abi_1.insertAssetsRequestSchema, abi_1.insertAssetsResponseSchema); } async verifyAssets(req) { return this._call('verifyAssets', req, abi_1.verifyAssetsRequestSchema, abi_1.verifyAssetsResponseSchema); } async beforeTransactionsExecute(req) { return this._call('beforeTransactionsExecute', req, abi_1.beforeTransactionsExecuteRequestSchema, abi_1.beforeTransactionsExecuteResponseSchema); } async afterTransactionsExecute(req) { return this._call('afterTransactionsExecute', req, abi_1.afterTransactionsExecuteRequestSchema, abi_1.afterTransactionsExecuteResponseSchema); } async verifyTransaction(req) { return this._call('verifyTransaction', req, abi_1.verifyTransactionRequestSchema, abi_1.verifyTransactionResponseSchema); } async executeTransaction(req) { return this._call('executeTransaction', req, abi_1.executeTransactionRequestSchema, abi_1.executeTransactionResponseSchema); } async commit(req) { return this._call('commit', req, abi_1.commitRequestSchema, abi_1.commitResponseSchema); } async revert(req) { return this._call('revert', req, abi_1.revertRequestSchema, abi_1.revertResponseSchema); } async clear(req) { return this._call('clear', req, abi_1.clearRequestSchema, abi_1.clearResponseSchema); } async finalize(req) { return this._call('finalize', req, abi_1.finalizeRequestSchema, abi_1.finalizeResponseSchema); } async getMetadata(req) { return this._call('getMetadata', req, abi_1.metadataRequestSchema, abi_1.metadataResponseSchema); } async query(req) { return this._call('query', req, abi_1.queryRequestSchema, abi_1.queryResponseSchema); } async prove(req) { return this._call('prove', req, abi_1.proveRequestSchema, abi_1.proveResponseSchema); } async _call(method, req, requestSchema, respSchema) { const params = Object.keys(requestSchema.properties).length > 0 ? lisk_codec_1.codec.encode(requestSchema, req) : Buffer.alloc(0); const requestBody = { id: this._globalID, method, params, }; this._logger.debug({ method: requestBody.method, id: requestBody.id, file: 'abi_client' }, 'Requesting ABI server'); const encodedRequest = lisk_codec_1.codec.encode(abi_1.ipcRequestSchema, requestBody); await this._dealer.send([encodedRequest]); const response = defer(); this._pendingRequests[this._globalID.toString()] = response; this._globalID += BigInt(1); if (this._globalID >= MAX_UINT64) { this._globalID = BigInt(0); } const resp = await Promise.race([ response.promise, timeout(DEFAULT_TIMEOUT, `Response not received in ${DEFAULT_TIMEOUT}ms`), ]); this._logger.debug({ method: requestBody.method, id: requestBody.id, file: 'abi_client' }, 'Received response from ABI server'); const decodedResp = Object.keys(respSchema.properties).length > 0 ? lisk_codec_1.codec.decode(respSchema, resp) : {}; return decodedResp; } async _listenToRPCResponse() { for await (const [message] of this._dealer) { let response; try { response = lisk_codec_1.codec.decode(abi_1.ipcResponseSchema, message); } catch (error) { this._logger.debug({ err: error }, 'Failed to decode ABI response'); continue; } const deferred = this._pendingRequests[response.id.toString()]; if (!deferred) { continue; } if (!response.success) { deferred.reject(new Error(response.error.message)); } else { deferred.resolve(response.result); } delete this._pendingRequests[response.id.toString()]; } } } exports.ABIClient = ABIClient; //# sourceMappingURL=abi_client.js.map