UNPKG

js-moi-manifest

Version:

Module to encode and decode MOI Logic Engine input and output.

428 lines 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Schema = exports.isClass = exports.isMap = exports.isArray = exports.isPrimitiveType = void 0; const js_moi_utils_1 = require("js-moi-utils"); const ARRAY_MATCHER_REGEX = /^\[(\d*)\]/; const primitiveTypes = ["null", "bool", "bytes", "address", "string", "u64", "u256", "i64", "i256", "bigint"]; const isPrimitiveType = (type) => { return primitiveTypes.includes(type); }; exports.isPrimitiveType = isPrimitiveType; const isArray = (type) => { return ARRAY_MATCHER_REGEX.test(type); }; exports.isArray = isArray; const isMap = (type) => { return type.startsWith("map"); }; exports.isMap = isMap; const isClass = (type, classDefs) => { return classDefs.has(type); }; exports.isClass = isClass; /** * Schema is a class that provides schema parsing functionality for encoding and * decoding manifest, arguments, logic states and other data based on * a predefined schema. It supports parsing fields and generating a schema for * decoding purposes. * * @class */ class Schema { elements; classDefs; constructor(elements, classDefs) { this.elements = elements; this.classDefs = classDefs; } static PISA_ENGINE_SCHEMA = { kind: "struct", fields: { kind: { kind: "string", }, flags: { kind: "array", fields: { values: { kind: "string", }, }, } }, }; static PISA_DEPS_SCHEMA = { kind: "array", fields: { values: { kind: "integer", }, }, }; static PISA_TYPE_FIELD_SCHEMA = { kind: "array", fields: { values: { kind: "struct", fields: { slot: { kind: "integer", }, label: { kind: "string", }, type: { kind: "string", }, }, }, }, }; static PISA_METHOD_FIELD_SCHEMA = { kind: "array", fields: { values: { kind: "struct", fields: { ptr: { kind: "integer", }, code: { kind: "integer", }, }, }, }, }; static PISA_INSTRUCTIONS_SCHEMA = { kind: "struct", fields: { bin: { kind: "bytes", }, hex: { kind: "string", }, asm: { kind: "array", fields: { values: { kind: "string", }, }, }, }, }; static PISA_STATE_SCHEMA = { kind: "struct", fields: { mode: { kind: "string", }, fields: { ...Schema.PISA_TYPE_FIELD_SCHEMA, }, }, }; static PISA_CONSTANT_SCHEMA = { kind: "struct", fields: { type: { kind: "string", }, value: { kind: "string", }, }, }; static PISA_TYPEDEF_SCHEMA = { kind: "string", fields: {}, }; static PISA_CLASS_SCHEMA = { kind: "struct", fields: { name: { kind: "string", }, fields: { ...Schema.PISA_TYPE_FIELD_SCHEMA, }, methods: { ...Schema.PISA_METHOD_FIELD_SCHEMA, }, }, }; static PISA_ROUTINE_SCHEMA = { kind: "struct", fields: { name: { kind: "string", }, mode: { kind: "string", }, kind: { kind: "string", }, accepts: { ...Schema.PISA_TYPE_FIELD_SCHEMA, }, returns: { ...Schema.PISA_TYPE_FIELD_SCHEMA, }, executes: { ...Schema.PISA_INSTRUCTIONS_SCHEMA, }, catches: { kind: "array", fields: { values: { kind: "string", }, }, }, }, }; static PISA_METHOD_SCHEMA = { kind: "struct", fields: { name: { kind: "string", }, class: { kind: "string", }, mutable: { kind: "bool", }, accepts: { ...Schema.PISA_TYPE_FIELD_SCHEMA, }, returns: { ...Schema.PISA_TYPE_FIELD_SCHEMA, }, executes: { ...Schema.PISA_INSTRUCTIONS_SCHEMA, }, catches: { kind: "array", fields: { values: { kind: "string", }, }, }, }, }; static PISA_EVENT_SCHEMA = { kind: "struct", fields: { name: { kind: "string", }, topics: { kind: "integer", }, fields: { ...Schema.PISA_TYPE_FIELD_SCHEMA, } } }; static PISA_EXCEPTION_SCHEMA = { kind: "struct", fields: { class: { kind: "string", }, error: { kind: "string", }, revert: { kind: "bool", }, trace: { kind: "array", fields: { values: { kind: "string", }, }, }, }, }; static PISA_RESULT_SCHEMA = { kind: "struct", fields: { outputs: { kind: "bytes", }, error: { kind: "bytes", }, }, }; /** * Extracts the array data type from the provided data type string. * * @param {string} dataType - The array data type, eg:"[]u64". * @returns {string} The extracted array data type. * @throws {Error} If the array type is invalid or unsupported. */ static extractArrayDataType(dataType) { if (!(0, exports.isArray)(dataType)) { js_moi_utils_1.ErrorUtils.throwError("Invalid array type: The provided data type is not an array.", js_moi_utils_1.ErrorCode.INVALID_ARGUMENT); } const type = dataType.replace(ARRAY_MATCHER_REGEX, ""); if (type === "") { js_moi_utils_1.ErrorUtils.throwError("Failed to extract array type: The array type could not be determined.", js_moi_utils_1.ErrorCode.INVALID_ARGUMENT); } return type; } /** * Extracts the key and value data types from the provided map data type string. * * @param {string} dataType - The map data type. eg:"map[u64]string". * @returns The extracted key and value data types as a tuple. * @throws {Error} If the map data type is invalid or unsupported. */ static extractMapDataType(dataType) { let brackets = []; let startIndex = 0; let endIndex = 0; for (let i = 0; i < dataType.length; i++) { if (dataType.charAt(i) == "[") { if (startIndex === 0) { startIndex = i + 1; } brackets.push("["); } else if (dataType.charAt(i) == "]") { brackets.pop(); if (brackets.length === 0) { endIndex = i; break; } } } const key = dataType.slice(startIndex, endIndex); const value = dataType.replace("map[" + key + "]", ""); if (!key || !value) { js_moi_utils_1.ErrorUtils.throwError("Failed to extract map type: The key or value type of the map could not be determined.", js_moi_utils_1.ErrorCode.INVALID_ARGUMENT); } return [key, value]; } /** * Converts the primitive data type to a standardized representation. * * @param {string} type - The primitive data type. * @returns {string} The converted data type. * @throws {Error} If the data type is unsupported. */ static convertPrimitiveDataType(type) { switch (type) { case "null": return "null"; case "bool": return "bool"; case "bytes": case "address": return "bytes"; case "string": return "string"; case "u64": case "u256": case "i64": case "i256": case "bigint": return "integer"; default: js_moi_utils_1.ErrorUtils.throwError("Unsupported data type!", js_moi_utils_1.ErrorCode.UNSUPPORTED_OPERATION); } } /** * Parses the fields of a class data type and generates the schema for the class. * * @param {string} className - The name of the class. * @returns {object} The schema for the class. */ static parseClassFields(className, classDef, elements) { const ptr = classDef.get(className); if (ptr === undefined) { js_moi_utils_1.ErrorUtils.throwError(`Invalid class name: ${className}`, js_moi_utils_1.ErrorCode.INVALID_ARGUMENT); } const element = elements.get(ptr); const schema = { kind: "struct", fields: {}, }; element.data = element.data; Object.values(element.data.fields).forEach((field) => { schema.fields[field.label] = Schema.parseDataType(field.type, classDef, elements); }); return schema; } /** * Parses a data type and generates the corresponding schema based on the * data type. The parsing is performed recursively to handle nested data types, * such as arrays, maps and class. * * @param {string} type - The data type string. * @returns {object} The schema generated based on the data type. * @throws {Error} If the data type is unsupported. */ static parseDataType(type, classDef, elements) { switch (true) { case (0, exports.isPrimitiveType)(type): return { kind: Schema.convertPrimitiveDataType(type), }; case (0, exports.isArray)(type): const values = Schema.extractArrayDataType(type); return { kind: "array", fields: { values: Schema.parseDataType(values, classDef, elements), }, }; case (0, exports.isMap)(type): const [key, value] = Schema.extractMapDataType(type); return { kind: "map", fields: { keys: Schema.parseDataType(key, classDef, elements), values: Schema.parseDataType(value, classDef, elements), }, }; case (0, exports.isClass)(type, classDef): return this.parseClassFields(type, classDef, elements); default: js_moi_utils_1.ErrorUtils.throwError(`Unsupported data type: ${type}!`, js_moi_utils_1.ErrorCode.UNSUPPORTED_OPERATION); } } /** * Parses an array of fields and generates the schema based on the fields. * * @param {LogicManifest.TypeField[]} fields - The array of fields. * @returns {PoloSchema} The generated schema based on the fields. * @throws {Error} If the fields are invalid or contain unsupported data types. */ parseFields(fields) { const schema = { kind: "struct", fields: {}, }; if (!Array.isArray(fields)) { js_moi_utils_1.ErrorUtils.throwError("Invalid fields: Fields must be an array.", js_moi_utils_1.ErrorCode.INVALID_ARGUMENT); } fields.forEach((field) => { if (!field || !(field.label && field.type)) { js_moi_utils_1.ErrorUtils.throwError("Invalid field: Each field must have a label and a type.", js_moi_utils_1.ErrorCode.INVALID_ARGUMENT); } schema.fields[field.label] = Schema.parseDataType(field.type, this.classDefs, this.elements); }); return schema; } } exports.Schema = Schema; //# sourceMappingURL=schema.js.map