lisk-framework
Version:
Lisk blockchain application platform
152 lines • 6.47 kB
JavaScript
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
;