UNPKG

@fuel-ts/abi-typegen

Version:

Generates Typescript definitions from Sway ABI Json files

1,657 lines (1,530 loc) • 53.6 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; // src/cli.ts var cli_exports = {}; __export(cli_exports, { configureCliOptions: () => configureCliOptions, resolveProgramType: () => resolveProgramType, run: () => run, runCliAction: () => runCliAction }); module.exports = __toCommonJS(cli_exports); var import_versions2 = require("@fuel-ts/versions"); var import_commander = require("commander"); // src/runTypegen.ts var import_errors9 = require("@fuel-ts/errors"); var import_fs3 = require("fs"); var import_glob = require("glob"); var import_mkdirp = __toESM(require("mkdirp")); var import_path4 = require("path"); var import_rimraf = __toESM(require("rimraf")); // src/AbiTypeGen.ts var import_errors8 = require("@fuel-ts/errors"); // src/abi/Abi.ts var import_errors4 = require("@fuel-ts/errors"); var import_utils = require("@fuel-ts/utils"); // src/utils/findType.ts var import_errors = require("@fuel-ts/errors"); function findType(params) { const { types, typeId } = params; const foundType = types.find(({ rawAbiType: { typeId: tid } }) => tid === typeId); if (!foundType) { throw new import_errors.FuelError(import_errors.ErrorCode.TYPE_ID_NOT_FOUND, `Type ID not found: ${typeId}.`); } foundType.parseComponentsAttributes({ types }); return foundType; } // src/abi/configurable/Configurable.ts var Configurable = class { name; type; rawAbiConfigurable; constructor(params) { const { types, rawAbiConfigurable } = params; this.name = rawAbiConfigurable.name; this.rawAbiConfigurable = rawAbiConfigurable; this.type = findType({ types, typeId: rawAbiConfigurable.configurableType.type }); } }; // src/utils/makeConfigurable.ts function makeConfigurable(params) { const { types, rawAbiConfigurable } = params; return new Configurable({ types, rawAbiConfigurable }); } // src/utils/parseConfigurables.ts function parseConfigurables(params) { const { types, rawAbiConfigurables } = params; const configurables = rawAbiConfigurables.map( (rawAbiConfigurable) => makeConfigurable({ types, rawAbiConfigurable }) ); return configurables; } // src/utils/parseTypeArguments.ts function parseTypeArguments(params) { const { types, typeArguments, parentTypeId, target } = params; const attributeKey = `${target}Label`; const buffer = []; let parentType; let parentLabel; if (parentTypeId !== void 0) { parentType = findType({ types, typeId: parentTypeId }); parentLabel = parentType.attributes[attributeKey]; } typeArguments.forEach((typeArgument) => { let currentLabel; const currentTypeId = typeArgument.type; try { const currentType = findType({ types, typeId: currentTypeId }); currentLabel = currentType.attributes[attributeKey]; } catch (_err) { currentLabel = "void"; } if (typeArgument.typeArguments) { const nestedParsed = parseTypeArguments({ types, target, parentTypeId: typeArgument.type, typeArguments: typeArgument.typeArguments }); buffer.push(nestedParsed); } else { buffer.push(`${currentLabel}`); } }); let output = buffer.join(", "); if (parentLabel) { output = `${parentLabel}<${output}>`; } return output; } // src/abi/functions/Function.ts var Function = class { name; types; rawAbiFunction; attributes; constructor(params) { this.rawAbiFunction = params.rawAbiFunction; this.types = params.types; this.name = params.rawAbiFunction.name; this.attributes = { inputs: this.bundleInputTypes(), output: this.bundleOutputTypes(), prefixedInputs: this.bundleInputTypes(true) }; } bundleInputTypes(shouldPrefixParams = false) { const { types } = this; const inputs = this.rawAbiFunction.inputs.map((input) => { const { name, type: typeId, typeArguments } = input; const type = findType({ types, typeId }); let typeDecl; if (typeArguments) { typeDecl = parseTypeArguments({ types, target: "input" /* INPUT */, parentTypeId: typeId, typeArguments }); } else { typeDecl = type.attributes.inputLabel; } if (shouldPrefixParams) { return `${name}: ${typeDecl}`; } return typeDecl; }); return inputs.join(", "); } bundleOutputTypes() { return parseTypeArguments({ types: this.types, target: "output" /* OUTPUT */, typeArguments: [this.rawAbiFunction.output] }); } getDeclaration() { const { name } = this; const { prefixedInputs, output } = this.attributes; const decl = `${name}: InvokeFunction<[${prefixedInputs}], ${output}>`; return decl; } }; // src/utils/makeFunction.ts function makeFunction(params) { const { types, rawAbiFunction } = params; return new Function({ types, rawAbiFunction }); } // src/utils/parseFunctions.ts function parseFunctions(params) { const { types, rawAbiFunctions } = params; const functions = rawAbiFunctions.map( (rawAbiFunction) => makeFunction({ types, rawAbiFunction }) ); return functions; } // src/utils/makeType.ts var import_errors3 = require("@fuel-ts/errors"); // src/abi/types/AType.ts var AType = class { rawAbiType; attributes; requiredFuelsMembersImports; constructor(params) { this.rawAbiType = params.rawAbiType; this.attributes = { inputLabel: "unknown", outputLabel: "unknown" }; this.requiredFuelsMembersImports = []; } }; // src/abi/types/ArrayType.ts var _ArrayType = class extends AType { name = "array"; static isSuitableFor(params) { return _ArrayType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(params) { const { types } = params; const { type } = this.rawAbiType; const arrayLen = Number(type.match(_ArrayType.MATCH_REGEX)?.[1]); const inputs = []; const outputs = []; this.rawAbiType.components?.forEach((component) => { const { type: typeId, typeArguments } = component; if (!typeArguments) { const { attributes } = findType({ types, typeId }); inputs.push(attributes.inputLabel); outputs.push(attributes.outputLabel); } else { const inputLabel = parseTypeArguments({ types, typeArguments, parentTypeId: typeId, target: "input" /* INPUT */ }); const outputLabel = parseTypeArguments({ types, typeArguments, parentTypeId: typeId, target: "output" /* OUTPUT */ }); inputs.push(inputLabel); outputs.push(outputLabel); } }); const inputTypes = Array(arrayLen).fill(inputs[0]).join(", "); const outputTypes = Array(arrayLen).fill(outputs[0]).join(", "); this.attributes = { inputLabel: `[${inputTypes}]`, outputLabel: `[${outputTypes}]` }; return this.attributes; } }; var ArrayType = _ArrayType; // Note: the array length expressed in '; 2]' could be any length __publicField(ArrayType, "swayType", "[_; 2]"); __publicField(ArrayType, "MATCH_REGEX", /^\[_; ([0-9]+)\]$/m); // src/abi/types/StrType.ts var _StrType = class extends AType { name = "str"; static isSuitableFor(params) { return _StrType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { this.attributes = { inputLabel: "string", outputLabel: "string" }; return this.attributes; } }; var StrType = _StrType; // Note: the str length expressed in '[3]' could be any length __publicField(StrType, "swayType", "str[3]"); __publicField(StrType, "MATCH_REGEX", /^str\[(.+)\]$/m); // src/abi/types/B256Type.ts var _B256Type = class extends StrType { name = "b256"; static isSuitableFor(params) { return _B256Type.MATCH_REGEX.test(params.type); } }; var B256Type = _B256Type; __publicField(B256Type, "swayType", "b256"); __publicField(B256Type, "MATCH_REGEX", /^b256$/m); // src/abi/types/B512Type.ts var _B512Type = class extends B256Type { name = "b512"; static isSuitableFor(params) { return _B512Type.MATCH_REGEX.test(params.type); } }; var B512Type = _B512Type; __publicField(B512Type, "swayType", "struct B512"); __publicField(B512Type, "MATCH_REGEX", /^struct B512$/m); // src/abi/types/BoolType.ts var _BoolType = class extends AType { name = "bool"; static isSuitableFor(params) { return _BoolType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { this.attributes = { inputLabel: "boolean", outputLabel: "boolean" }; return this.attributes; } }; var BoolType = _BoolType; __publicField(BoolType, "swayType", "bool"); __publicField(BoolType, "MATCH_REGEX", /^bool$/m); // src/abi/types/BytesType.ts var _BytesType = class extends ArrayType { name = "bytes"; static isSuitableFor(params) { return _BytesType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { const capitalizedName = "Bytes"; this.attributes = { inputLabel: capitalizedName, outputLabel: capitalizedName }; this.requiredFuelsMembersImports = [capitalizedName]; return this.attributes; } }; var BytesType = _BytesType; __publicField(BytesType, "swayType", "struct Bytes"); __publicField(BytesType, "MATCH_REGEX", /^struct Bytes/m); // src/utils/extractStructName.ts var import_errors2 = require("@fuel-ts/errors"); function extractStructName(params) { const { rawAbiType, regex } = params; const match = rawAbiType.type.match(params.regex)?.[1]; if (!match) { let errorMessage = `Couldn't extract struct name with: '${regex}'. `; errorMessage += `Check your JSON ABI. [source] `; errorMessage += `${JSON.stringify(rawAbiType, null, 2)}`; throw new import_errors2.FuelError(import_errors2.ErrorCode.JSON_ABI_ERROR, errorMessage); } return match; } // src/abi/types/EnumType.ts var _EnumType = class extends AType { name = "enum"; static isSuitableFor(params) { const isAMatch = _EnumType.MATCH_REGEX.test(params.type); const shouldBeIgnored = _EnumType.IGNORE_REGEX.test(params.type); return isAMatch && !shouldBeIgnored; } parseComponentsAttributes(_params) { const structName = this.getStructName(); this.attributes = { structName, inputLabel: `${structName}Input`, outputLabel: `${structName}Output` }; return this.attributes; } getStructName() { const name = extractStructName({ rawAbiType: this.rawAbiType, regex: _EnumType.MATCH_REGEX }); return name; } getNativeEnum(params) { const { types } = params; const typeHash = types.reduce( (hash, row) => ({ ...hash, [row.rawAbiType.typeId]: row }), {} ); const { components } = this.rawAbiType; const enumComponents = components; if (!enumComponents.every(({ type }) => !typeHash[type])) { return void 0; } return enumComponents.map(({ name }) => `${name} = '${name}'`).join(", "); } getStructContents(params) { const { types, target } = params; const { components } = this.rawAbiType; const enumComponents = components; const attributeKey = `${target}Label`; const contents = enumComponents.map((component) => { const { name, type: typeId } = component; if (typeId === 0) { return `${name}: []`; } const { attributes } = findType({ types, typeId }); return `${name}: ${attributes[attributeKey]}`; }); return contents.join(", "); } }; var EnumType = _EnumType; __publicField(EnumType, "swayType", "enum MyEnumName"); __publicField(EnumType, "MATCH_REGEX", /^enum (.+)$/m); __publicField(EnumType, "IGNORE_REGEX", /^enum Option$/m); // src/abi/types/EvmAddressType.ts var _EvmAddressType = class extends AType { name = "evmAddress"; static isSuitableFor(params) { return _EvmAddressType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { const capitalizedName = "EvmAddress"; this.attributes = { inputLabel: capitalizedName, outputLabel: capitalizedName }; this.requiredFuelsMembersImports = [capitalizedName]; return this.attributes; } }; var EvmAddressType = _EvmAddressType; __publicField(EvmAddressType, "swayType", "struct EvmAddress"); __publicField(EvmAddressType, "MATCH_REGEX", /^struct EvmAddress$/m); // src/abi/types/GenericType.ts var _GenericType = class extends AType { name = "generic"; static isSuitableFor(params) { return _GenericType.MATCH_REGEX.test(params.type); } getStructName() { const name = extractStructName({ rawAbiType: this.rawAbiType, regex: _GenericType.MATCH_REGEX }); return name; } parseComponentsAttributes(_params) { const label = this.getStructName(); this.attributes = { inputLabel: label, outputLabel: label }; return this.attributes; } }; var GenericType = _GenericType; __publicField(GenericType, "swayType", "generic T"); __publicField(GenericType, "MATCH_REGEX", /^generic ([^\s]+)$/m); // src/abi/types/OptionType.ts var _OptionType = class extends AType { name = "option"; static isSuitableFor(params) { return _OptionType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { this.attributes = { inputLabel: `Option`, outputLabel: `Option` }; return this.attributes; } }; var OptionType = _OptionType; __publicField(OptionType, "swayType", "enum Option"); __publicField(OptionType, "MATCH_REGEX", /^enum Option$/m); // src/abi/types/U8Type.ts var _U8Type = class extends AType { name = "u8"; constructor(params) { super(params); this.attributes = { inputLabel: `BigNumberish`, outputLabel: `number` }; this.requiredFuelsMembersImports = [this.attributes.inputLabel]; } static isSuitableFor(params) { return _U8Type.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { return this.attributes; } }; var U8Type = _U8Type; __publicField(U8Type, "swayType", "u8"); __publicField(U8Type, "MATCH_REGEX", /^u8$/m); // src/abi/types/U64Type.ts var _U64Type = class extends U8Type { name = "u64"; parseComponentsAttributes(_params) { this.attributes = { inputLabel: `BigNumberish`, outputLabel: `BN` }; this.requiredFuelsMembersImports = Object.values(this.attributes); return this.attributes; } static isSuitableFor(params) { return _U64Type.MATCH_REGEX.test(params.type); } }; var U64Type = _U64Type; __publicField(U64Type, "swayType", "u64"); __publicField(U64Type, "MATCH_REGEX", /^u64$/m); // src/abi/types/RawUntypedPtr.ts var _RawUntypedPtr = class extends U64Type { name = "rawUntypedPtr"; static isSuitableFor(params) { return _RawUntypedPtr.MATCH_REGEX.test(params.type); } }; var RawUntypedPtr = _RawUntypedPtr; __publicField(RawUntypedPtr, "swayType", "raw untyped ptr"); __publicField(RawUntypedPtr, "MATCH_REGEX", /^raw untyped ptr$/m); // src/abi/types/RawUntypedSlice.ts var _RawUntypedSlice = class extends ArrayType { name = "rawUntypedSlice"; static isSuitableFor(params) { return _RawUntypedSlice.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { const capitalizedName = "RawSlice"; this.attributes = { inputLabel: capitalizedName, outputLabel: capitalizedName }; this.requiredFuelsMembersImports = [capitalizedName]; return this.attributes; } }; var RawUntypedSlice = _RawUntypedSlice; __publicField(RawUntypedSlice, "swayType", "raw untyped slice"); __publicField(RawUntypedSlice, "MATCH_REGEX", /^raw untyped slice$/m); // src/abi/types/StdStringType.ts var _StdStringType = class extends AType { name = "stdString"; static isSuitableFor(params) { return _StdStringType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { const capitalizedName = "StdString"; this.attributes = { inputLabel: capitalizedName, outputLabel: capitalizedName }; this.requiredFuelsMembersImports = [capitalizedName]; return this.attributes; } }; var StdStringType = _StdStringType; __publicField(StdStringType, "swayType", "struct String"); __publicField(StdStringType, "MATCH_REGEX", /^struct String/m); // src/abi/types/StrSliceType.ts var _StrSliceType = class extends AType { name = "strSlice"; static isSuitableFor(params) { return _StrSliceType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(_params) { this.attributes = { inputLabel: "StrSlice", outputLabel: "StrSlice" }; return this.attributes; } }; var StrSliceType = _StrSliceType; __publicField(StrSliceType, "swayType", "str"); __publicField(StrSliceType, "MATCH_REGEX", /^str$/m); // src/abi/types/StructType.ts var _StructType = class extends AType { name = "struct"; static isSuitableFor(params) { const isAMatch = _StructType.MATCH_REGEX.test(params.type); const shouldBeIgnored = _StructType.IGNORE_REGEX.test(params.type); return isAMatch && !shouldBeIgnored; } parseComponentsAttributes(_params) { const structName = this.getStructName(); this.attributes = { structName, inputLabel: `${structName}Input`, outputLabel: `${structName}Output` }; return this.attributes; } getStructName() { const name = extractStructName({ rawAbiType: this.rawAbiType, regex: _StructType.MATCH_REGEX }); return name; } getStructContents(params) { const { types, target } = params; const { components } = this.rawAbiType; const structComponents = components; const members = structComponents.map((component) => { const { name, type: typeId, typeArguments } = component; const type = findType({ types, typeId }); let typeDecl; if (typeArguments) { typeDecl = parseTypeArguments({ types, target, parentTypeId: typeId, typeArguments }); } else { const attributeKey = `${target}Label`; typeDecl = type.attributes[attributeKey]; } return `${name}: ${typeDecl}`; }); return members.join(", "); } getStructDeclaration(params) { const { types } = params; const { typeParameters } = this.rawAbiType; if (typeParameters) { const structs = typeParameters.map((typeId) => findType({ types, typeId })); const labels = structs.map(({ attributes: { inputLabel } }) => inputLabel); return `<${labels.join(", ")}>`; } return ""; } }; var StructType = _StructType; __publicField(StructType, "swayType", "struct MyStruct"); __publicField(StructType, "MATCH_REGEX", /^struct (.+)$/m); __publicField(StructType, "IGNORE_REGEX", /^struct (Vec|RawVec|EvmAddress|Bytes|String)$/m); // src/abi/types/TupleType.ts var _TupleType = class extends AType { name = "tupple"; static isSuitableFor(params) { return _TupleType.MATCH_REGEX.test(params.type); } parseComponentsAttributes(params) { const { types } = params; const inputs = []; const outputs = []; this.rawAbiType.components?.forEach((component) => { const { type: typeId, typeArguments } = component; if (!typeArguments) { const { attributes } = findType({ types, typeId }); inputs.push(attributes.inputLabel); outputs.push(attributes.outputLabel); } else { const inputLabel = parseTypeArguments({ types, typeArguments, parentTypeId: typeId, target: "input" /* INPUT */ }); const outputLabel = parseTypeArguments({ types, typeArguments, parentTypeId: typeId, target: "output" /* OUTPUT */ }); inputs.push(inputLabel); outputs.push(outputLabel); } }); this.attributes = { inputLabel: `[${inputs.join(", ")}]`, outputLabel: `[${outputs.join(", ")}]` }; return this.attributes; } }; var TupleType = _TupleType; // Note: a tuple can have more/less than 3x items (like the one bellow) __publicField(TupleType, "swayType", "(_, _, _)"); __publicField(TupleType, "MATCH_REGEX", /^\([_,\s]+\)$/m); // src/abi/types/U16Type.ts var _U16Type = class extends U8Type { name = "u16"; static isSuitableFor(params) { return _U16Type.MATCH_REGEX.test(params.type); } }; var U16Type = _U16Type; __publicField(U16Type, "swayType", "u16"); __publicField(U16Type, "MATCH_REGEX", /^u16$/m); // src/abi/types/U256Type.ts var _U256Type = class extends U64Type { name = "u256"; static isSuitableFor(params) { return _U256Type.MATCH_REGEX.test(params.type); } }; var U256Type = _U256Type; __publicField(U256Type, "swayType", "u256"); __publicField(U256Type, "MATCH_REGEX", /^u256$/m); // src/abi/types/U32Type.ts var _U32Type = class extends U8Type { name = "u32"; static isSuitableFor(params) { return _U32Type.MATCH_REGEX.test(params.type); } }; var U32Type = _U32Type; __publicField(U32Type, "swayType", "u32"); __publicField(U32Type, "MATCH_REGEX", /^u32$/m); // src/abi/types/VectorType.ts var _VectorType = class extends ArrayType { name = "vector"; static isSuitableFor(params) { const isAMatch = _VectorType.MATCH_REGEX.test(params.type); const shouldBeIgnored = _VectorType.IGNORE_REGEX.test(params.type); return isAMatch && !shouldBeIgnored; } parseComponentsAttributes(_params) { this.attributes = { inputLabel: `Vec`, outputLabel: `Vec` }; return this.attributes; } }; var VectorType = _VectorType; __publicField(VectorType, "swayType", "struct Vec"); __publicField(VectorType, "MATCH_REGEX", /^struct Vec/m); __publicField(VectorType, "IGNORE_REGEX", /^struct RawVec$/m); // src/utils/supportedTypes.ts var supportedTypes = [ ArrayType, B256Type, B512Type, BoolType, BytesType, EnumType, GenericType, OptionType, RawUntypedPtr, RawUntypedSlice, StdStringType, StrType, StrSliceType, StructType, TupleType, U16Type, U32Type, U64Type, U256Type, U8Type, VectorType, EvmAddressType ]; // src/utils/makeType.ts function makeType(params) { const { rawAbiType } = params; const { type } = rawAbiType; const TypeClass = supportedTypes.find((tc) => tc.isSuitableFor({ type })); if (!TypeClass) { throw new import_errors3.FuelError(import_errors3.ErrorCode.TYPE_NOT_SUPPORTED, `Type not supported: ${type}`); } return new TypeClass(params); } // src/utils/shouldSkipAbiType.ts function shouldSkipAbiType(params) { const ignoreList = ["()", "struct RawVec"]; const shouldSkip = ignoreList.indexOf(params.type) >= 0; return shouldSkip; } // src/utils/parseTypes.ts function parseTypes(params) { const types = []; params.rawAbiTypes.forEach((rawAbiType) => { const { type } = rawAbiType; const skip = shouldSkipAbiType({ type }); if (!skip) { const parsedType = makeType({ rawAbiType }); types.push(parsedType); } }); types.forEach((type) => { type.parseComponentsAttributes({ types }); }); return types; } // src/abi/Abi.ts var Abi = class { name; programType; filepath; outputDir; commonTypesInUse = []; rawContents; hexlifiedBinContents; storageSlotsContents; types; functions; configurables; constructor(params) { const { filepath, outputDir, rawContents, hexlifiedBinContents, programType, storageSlotsContents } = params; const abiNameRegex = /([^/]+)-abi\.json$/m; const abiName = filepath.match(abiNameRegex); const couldNotParseName = !abiName || abiName.length === 0; if (couldNotParseName) { throw new import_errors4.FuelError( import_errors4.ErrorCode.PARSE_FAILED, `Could not parse name from ABI file: ${filepath}.` ); } const name = `${(0, import_utils.normalizeString)(abiName[1])}Abi`; this.name = name; this.programType = programType; this.filepath = filepath; this.rawContents = rawContents; this.hexlifiedBinContents = hexlifiedBinContents; this.storageSlotsContents = storageSlotsContents; this.outputDir = outputDir; const { types, functions, configurables } = this.parse(); this.types = types; this.functions = functions; this.configurables = configurables; this.computeCommonTypesInUse(); } parse() { const { types: rawAbiTypes, functions: rawAbiFunctions, configurables: rawAbiConfigurables } = this.rawContents; const types = parseTypes({ rawAbiTypes }); const functions = parseFunctions({ rawAbiFunctions, types }); const configurables = parseConfigurables({ rawAbiConfigurables, types }); return { types, functions, configurables }; } computeCommonTypesInUse() { const customTypesTable = { option: "Option", enum: "Enum", vector: "Vec" }; this.commonTypesInUse = []; Object.keys(customTypesTable).forEach((typeName) => { const isInUse = !!this.types.find((t) => t.name === typeName); if (isInUse) { const commonTypeLabel = customTypesTable[typeName]; this.commonTypesInUse.push(commonTypeLabel); } }); } }; // src/types/enums/ProgramTypeEnum.ts var ProgramTypeEnum = /* @__PURE__ */ ((ProgramTypeEnum2) => { ProgramTypeEnum2["CONTRACT"] = "contract"; ProgramTypeEnum2["SCRIPT"] = "script"; ProgramTypeEnum2["PREDICATE"] = "predicate"; return ProgramTypeEnum2; })(ProgramTypeEnum || {}); // src/utils/assembleContracts.ts var import_path = require("path"); // src/templates/renderHbsTemplate.ts var import_versions = require("@fuel-ts/versions"); var import_handlebars = require("handlebars"); // src/templates/common/_header.hbs var header_default = "/* Autogenerated file. Do not edit manually. */\n\n/* tslint:disable */\n/* eslint-disable */\n\n/*\n Fuels version: {{FUELS}}\n Forc version: {{FORC}}\n Fuel-Core version: {{FUEL_CORE}}\n*/\n"; // src/templates/renderHbsTemplate.ts function renderHbsTemplate(params) { const { data, template } = params; const options = { strict: true, noEscape: true }; const renderTemplate = (0, import_handlebars.compile)(template, options); const renderHeaderTemplate = (0, import_handlebars.compile)(header_default, options); const text = renderTemplate({ ...data, header: renderHeaderTemplate(import_versions.versions) }); return text.replace(/[\n]{3,}/gm, "\n\n"); } // src/templates/common/common.hbs var common_default = "{{header}}\n\n/*\n Mimics Sway Enum, requires at least one Key-Value but\n does not raise error on multiple pairs.\n This is done in the abi-coder\n*/\nexport type Enum<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> &\n U[keyof U];\n\n/*\n Mimics Sway Option and Vectors.\n Vectors are treated like arrays in Typescript.\n*/\nexport type Option<T> = T | undefined;\n\nexport type Vec<T> = T[];\n"; // src/templates/common/common.ts function renderCommonTemplate() { const text = renderHbsTemplate({ template: common_default }); return text; } // src/templates/common/index.hbs var common_default2 = "{{header}}\n\n{{#if isGeneratingContracts}}\n{{#each abis}}\nexport type { {{name}} } from './{{name}}';\n{{/each}}\n{{/if}}\n\n{{#each abis}}\nexport { {{name}}__factory } from './factories/{{name}}__factory';\n{{/each}}\n"; // src/templates/common/index.ts function renderIndexTemplate(params) { const { abis } = params; const isGeneratingContracts = abis[0].programType === "contract" /* CONTRACT */; const text = renderHbsTemplate({ template: common_default2, data: { abis, isGeneratingContracts } }); return text; } // src/templates/contract/bytecode.hbs var bytecode_default = "{{header}}\n\nexport default '{{hexlifiedBytecode}}'"; // src/templates/contract/bytecode.ts function renderBytecodeTemplate(params) { const text = renderHbsTemplate({ template: bytecode_default, data: { hexlifiedBytecode: params.hexlifiedBytecode } }); return text; } // src/templates/utils/formatConfigurables.ts function formatConfigurables(params) { const { configurables } = params; const formattedConfigurables = configurables.map((c) => { const { name, type: { attributes: { inputLabel } } } = c; return { configurableName: name, configurableType: inputLabel }; }); return { formattedConfigurables }; } // src/templates/utils/formatEnums.ts function formatEnums(params) { const { types } = params; const enums = types.filter((t) => t.name === "enum").map((t) => { const et = t; const structName = et.getStructName(); const inputValues = et.getStructContents({ types, target: "input" /* INPUT */ }); const outputValues = et.getStructContents({ types, target: "output" /* OUTPUT */ }); const inputNativeValues = et.getNativeEnum({ types }); const outputNativeValues = et.getNativeEnum({ types }); return { structName, inputValues, outputValues, recycleRef: inputValues === outputValues, // reduces duplication inputNativeValues, outputNativeValues }; }); return { enums }; } // src/templates/utils/formatImports.ts var import_ramda = require("ramda"); var caseInsensitiveSort = (a, b) => a.toLowerCase().localeCompare(b.toLowerCase()); function formatImports(params) { const { types, baseMembers = [] } = params; const members = types.flatMap((t) => t.requiredFuelsMembersImports); const imports = (0, import_ramda.uniq)(baseMembers.concat(members).sort(caseInsensitiveSort)); return { imports: imports.length ? imports : void 0 }; } // src/templates/utils/formatStructs.ts function formatStructs(params) { const { types } = params; const structs = types.filter((t) => t.name === "struct").map((t) => { const st = t; const structName = st.getStructName(); const inputValues = st.getStructContents({ types, target: "input" /* INPUT */ }); const outputValues = st.getStructContents({ types, target: "output" /* OUTPUT */ }); const typeAnnotations = st.getStructDeclaration({ types }); return { structName, typeAnnotations, inputValues, outputValues, recycleRef: inputValues === outputValues // reduces duplication }; }); return { structs }; } // src/templates/contract/dts.hbs var dts_default = `{{header}} {{#if imports}} import type { {{#each imports}} {{this}}, {{/each}} } from 'fuels'; {{/if}} {{#if commonTypesInUse}} import type { {{commonTypesInUse}} } from "./common"; {{/if}} {{#each enums}} {{#if inputNativeValues}} export enum {{structName}}Input { {{inputNativeValues}} }; {{else}} export type {{structName}}Input = Enum<{ {{inputValues}} }>; {{/if}} {{#if outputNativeValues}} export enum {{structName}}Output { {{outputNativeValues}} }; {{else}} {{#if recycleRef}} export type {{structName}}Output = {{structName}}Input; {{else}} export type {{structName}}Output = Enum<{ {{outputValues}} }>; {{/if}} {{/if}} {{/each}} {{#each structs}} export type {{structName}}Input{{typeAnnotations}} = { {{inputValues}} }; {{#if recycleRef}} export type {{structName}}Output{{typeAnnotations}} = {{structName}}Input{{typeAnnotations}}; {{else}} export type {{structName}}Output{{typeAnnotations}} = { {{outputValues}} }; {{/if}} {{/each}} {{#if formattedConfigurables}} export type {{capitalizedName}}Configurables = { {{#each formattedConfigurables}} {{configurableName}}: {{configurableType}}; {{/each}} }; {{/if}} interface {{capitalizedName}}Interface extends Interface { functions: { {{#each functionsFragments}} {{this}}: FunctionFragment; {{/each}} }; {{#each encoders}} encodeFunctionData(functionFragment: '{{functionName}}', values: [{{input}}]): Uint8Array; {{/each}} {{#each decoders}} decodeFunctionData(functionFragment: '{{functionName}}', data: BytesLike): DecodedValue; {{/each}} } export class {{capitalizedName}} extends Contract { interface: {{capitalizedName}}Interface; functions: { {{#each functionsTypedefs}} {{this}}; {{/each}} }; } `; // src/templates/contract/dts.ts function renderDtsTemplate(params) { const { name: capitalizedName, types, functions, commonTypesInUse, configurables } = params.abi; const functionsTypedefs = functions.map((f) => f.getDeclaration()); const functionsFragments = functions.map((f) => f.name); const encoders = functions.map((f) => ({ functionName: f.name, input: f.attributes.inputs })); const decoders = functions.map((f) => ({ functionName: f.name })); const { enums } = formatEnums({ types }); const { structs } = formatStructs({ types }); const { imports } = formatImports({ types, baseMembers: [ "Interface", "FunctionFragment", "DecodedValue", "Contract", "BytesLike", "InvokeFunction" ] }); const { formattedConfigurables } = formatConfigurables({ configurables }); const text = renderHbsTemplate({ template: dts_default, data: { capitalizedName, commonTypesInUse: commonTypesInUse.join(", "), functionsTypedefs, functionsFragments, encoders, decoders, structs, enums, imports, formattedConfigurables } }); return text; } // src/templates/contract/factory.hbs var factory_default = '{{header}}\n\nimport { Interface, Contract, ContractFactory } from "fuels";\nimport type { Provider, Account, AbstractAddress, BytesLike, DeployContractOptions, StorageSlot } from "fuels";\nimport type { {{capitalizedName}}, {{capitalizedName}}Interface } from "../{{capitalizedName}}";\n\nconst _abi = {{abiJsonString}};\n\nconst _storageSlots: StorageSlot[] = {{storageSlotsJsonString}};\n\nexport class {{capitalizedName}}__factory {\n static readonly abi = _abi;\n\n static readonly storageSlots = _storageSlots;\n\n static createInterface(): {{capitalizedName}}Interface {\n return new Interface(_abi) as unknown as {{capitalizedName}}Interface\n }\n\n static connect(\n id: string | AbstractAddress,\n accountOrProvider: Account | Provider\n ): {{capitalizedName}} {\n return new Contract(id, _abi, accountOrProvider) as unknown as {{capitalizedName}}\n }\n\n static async deployContract(\n bytecode: BytesLike,\n wallet: Account,\n options: DeployContractOptions = {}\n ): Promise<{{capitalizedName}}> {\n const factory = new ContractFactory(bytecode, _abi, wallet);\n\n const { storageSlots } = {{capitalizedName}}__factory;\n\n const contract = await factory.deployContract({\n storageSlots,\n ...options,\n });\n\n return contract as unknown as {{capitalizedName}};\n }\n}\n'; // src/templates/contract/factory.ts function renderFactoryTemplate(params) { const { name: capitalizedName, rawContents, storageSlotsContents } = params.abi; const abiJsonString = JSON.stringify(rawContents, null, 2); const storageSlotsJsonString = storageSlotsContents ?? "[]"; const text = renderHbsTemplate({ template: factory_default, data: { capitalizedName, abiJsonString, storageSlotsJsonString } }); return text; } // src/utils/assembleContracts.ts function assembleContracts(params) { const { abis, outputDir } = params; const files = []; const usesCommonTypes = abis.find((a) => a.commonTypesInUse.length > 0); abis.forEach((abi) => { const { name } = abi; const dtsFilepath = `${outputDir}/${name}.d.ts`; const factoryFilepath = `${outputDir}/factories/${name}__factory.ts`; const hexBinFilePath = `${outputDir}/${name}.hex.ts`; const dts = { path: dtsFilepath, contents: renderDtsTemplate({ abi }) }; const factory = { path: factoryFilepath, contents: renderFactoryTemplate({ abi }) }; const hexBinFile = { path: hexBinFilePath, contents: renderBytecodeTemplate({ hexlifiedBytecode: abi.hexlifiedBinContents }) }; files.push(dts); files.push(factory); files.push(hexBinFile); }); const indexFile = { path: `${outputDir}/index.ts`, contents: renderIndexTemplate({ abis }) }; files.push(indexFile); if (usesCommonTypes) { const commonsFilepath = (0, import_path.join)(outputDir, "common.d.ts"); const file = { path: commonsFilepath, contents: renderCommonTemplate() }; files.push(file); } return files; } // src/utils/assemblePredicates.ts var import_path2 = require("path"); // src/templates/predicate/factory.ts var import_errors5 = require("@fuel-ts/errors"); // src/templates/predicate/factory.hbs var factory_default2 = `{{header}} {{#if imports}} import { {{#each imports}} {{this}}, {{/each}} } from 'fuels'; {{/if}} {{#if commonTypesInUse}} import type { {{commonTypesInUse}} } from "./common"; {{/if}} {{#each enums}} {{#if inputNativeValues}} export enum {{structName}}Input { {{inputNativeValues}} }; {{else}} export type {{structName}}Input = Enum<{ {{inputValues}} }>; {{/if}} {{#if outputNativeValues}} export enum {{structName}}Output { {{outputNativeValues}} }; {{else}} {{#if recycleRef}} export type {{structName}}Output = {{structName}}Input; {{else}} export type {{structName}}Output = Enum<{ {{outputValues}} }>; {{/if}} {{/if}} {{/each}} {{#each structs}} export type {{structName}}Input{{typeAnnotations}} = { {{inputValues}} }; {{#if recycleRef}} export type {{structName}}Output{{typeAnnotations}} = {{structName}}Input{{typeAnnotations}}; {{else}} export type {{structName}}Output{{typeAnnotations}} = { {{outputValues}} }; {{/if}} {{/each}} export type {{capitalizedName}}Configurables = { {{#each formattedConfigurables}} {{configurableName}}: {{configurableType}}; {{/each}} }; type {{capitalizedName}}Inputs = [{{inputs}}]; const _abi = {{abiJsonString}} const _bin = '{{hexlifiedBinString}}' export class {{capitalizedName}}__factory { static readonly abi = _abi static readonly bin = _bin; static createInstance(provider: Provider, configurables?: {{capitalizedName}}Configurables) { const { abi, bin } = {{capitalizedName}}__factory const predicate = new Predicate(bin, provider, abi, configurables); return predicate; } } `; // src/templates/predicate/factory.ts function renderFactoryTemplate2(params) { const { abi } = params; const { types, configurables } = abi; const { rawContents, name: capitalizedName, hexlifiedBinContents: hexlifiedBinString } = params.abi; const abiJsonString = JSON.stringify(rawContents, null, 2); const func = abi.functions.find((f) => f.name === "main"); if (!func) { throw new import_errors5.FuelError(import_errors5.ErrorCode.ABI_MAIN_METHOD_MISSING, `ABI doesn't have a 'main()' method.`); } const { enums } = formatEnums({ types }); const { structs } = formatStructs({ types }); const { imports } = formatImports({ types, baseMembers: ["Predicate", "Provider"] }); const { formattedConfigurables } = formatConfigurables({ configurables }); const { prefixedInputs: inputs, output } = func.attributes; const text = renderHbsTemplate({ template: factory_default2, data: { inputs, output, structs, enums, abiJsonString, hexlifiedBinString, capitalizedName, imports, formattedConfigurables } }); return text; } // src/utils/assemblePredicates.ts function assemblePredicates(params) { const { abis, outputDir } = params; const files = []; const usesCommonTypes = abis.find((a) => a.commonTypesInUse.length > 0); abis.forEach((abi) => { const { name } = abi; const factoryFilepath = `${outputDir}/factories/${name}__factory.ts`; const factory = { path: factoryFilepath, contents: renderFactoryTemplate2({ abi }) }; files.push(factory); }); const indexFile = { path: `${outputDir}/index.ts`, contents: renderIndexTemplate({ abis }) }; files.push(indexFile); if (usesCommonTypes) { const commonsFilepath = (0, import_path2.join)(outputDir, "common.d.ts"); const file = { path: commonsFilepath, contents: renderCommonTemplate() }; files.push(file); } return files; } // src/utils/assembleScripts.ts var import_path3 = require("path"); // src/templates/script/factory.ts var import_errors6 = require("@fuel-ts/errors"); // src/templates/script/factory.hbs var factory_default3 = `{{header}} {{#if imports}} import { {{#each imports}} {{this}}, {{/each}} } from 'fuels'; {{/if}} {{#if commonTypesInUse}} import type { {{commonTypesInUse}} } from "./common"; {{/if}} {{#each enums}} {{#if inputNativeValues}} export enum {{structName}}Input { {{inputNativeValues}} }; {{else}} export type {{structName}}Input = Enum<{ {{inputValues}} }>; {{/if}} {{#if outputNativeValues}} export enum {{structName}}Output { {{outputNativeValues}} }; {{else}} {{#if recycleRef}} export type {{structName}}Output = {{structName}}Input; {{else}} export type {{structName}}Output = Enum<{ {{outputValues}} }>; {{/if}} {{/if}} {{/each}} {{#each structs}} export type {{structName}}Input{{typeAnnotations}} = { {{inputValues}} }; {{#if recycleRef}} export type {{structName}}Output{{typeAnnotations}} = {{structName}}Input{{typeAnnotations}}; {{else}} export type {{structName}}Output{{typeAnnotations}} = { {{outputValues}} }; {{/if}} {{/each}} type {{capitalizedName}}Inputs = [{{inputs}}]; type {{capitalizedName}}Output = {{output}}; {{#if formattedConfigurables}} export type {{capitalizedName}}Configurables = { {{#each formattedConfigurables}} {{configurableName}}: {{configurableType}}; {{/each}} }; {{/if}} const _abi = {{abiJsonString}} const _bin = '{{hexlifiedBinString}}' export class {{capitalizedName}}__factory { static readonly abi = _abi static readonly bin = _bin static createInstance(wallet: Account) { const { abi, bin } = {{capitalizedName}}__factory const script = new Script< {{capitalizedName}}Inputs, {{capitalizedName}}Output >(bin, abi, wallet); return script; } } `; // src/templates/script/factory.ts function renderFactoryTemplate3(params) { const { abi } = params; const { types, configurables } = abi; const { rawContents, name: capitalizedName, hexlifiedBinContents: hexlifiedBinString } = params.abi; const abiJsonString = JSON.stringify(rawContents, null, 2); const func = abi.functions.find((f) => f.name === "main"); if (!func) { throw new import_errors6.FuelError(import_errors6.ErrorCode.ABI_MAIN_METHOD_MISSING, `ABI doesn't have a 'main()' method.`); } const { enums } = formatEnums({ types }); const { structs } = formatStructs({ types }); const { imports } = formatImports({ types, baseMembers: ["Script", "Account"] }); const { formattedConfigurables } = formatConfigurables({ configurables }); const { prefixedInputs: inputs, output } = func.attributes; const text = renderHbsTemplate({ template: factory_default3, data: { inputs, output, structs, enums, abiJsonString, hexlifiedBinString, capitalizedName, imports, formattedConfigurables } }); return text; } // src/utils/assembleScripts.ts function assembleScripts(params) { const { abis, outputDir } = params; const files = []; const usesCommonTypes = abis.find((a) => a.commonTypesInUse.length > 0); abis.forEach((abi) => { const { name } = abi; const factoryFilepath = `${outputDir}/factories/${name}__factory.ts`; const factory = { path: factoryFilepath, contents: renderFactoryTemplate3({ abi }) }; files.push(factory); }); const indexFile = { path: `${outputDir}/index.ts`, contents: renderIndexTemplate({ abis }) }; files.push(indexFile); if (usesCommonTypes) { const commonsFilepath = (0, import_path3.join)(outputDir, "common.d.ts"); const file = { path: commonsFilepath, contents: renderCommonTemplate() }; files.push(file); } return files; } // src/utils/validateBinFile.ts var import_errors7 = require("@fuel-ts/errors"); var upperFirst = (s) => s[0].toUpperCase() + s.slice(1); function validateBinFile(params) { const { abiFilepath, binFilepath, binExists, programType } = params; const isScript = programType === "script" /* SCRIPT */; if (!binExists && isScript) { throw new import_errors7.FuelError( import_errors7.ErrorCode.BIN_FILE_NOT_FOUND, [ `Could not find BIN file for counterpart ${upperFirst(programType)} ABI.`, ` - ABI: ${abiFilepath}`, ` - BIN: ${binFilepath}`, programType ].join("\n") ); } } // src/AbiTypeGen.ts var AbiTypeGen = class { abis; abiFiles; binFiles; storageSlotsFiles; outputDir; files; constructor(params) { const { abiFiles, binFiles, outputDir, programType, storageSlotsFiles } = params; this.outputDir = outputDir; this.abiFiles = abiFiles; this.binFiles = binFiles; this.storageSlotsFiles = storageSlotsFiles; this.abis = this.abiFiles.map((abiFile) => { const binFilepath = abiFile.path.replace("-abi.json", ".bin"); const relatedBinFile = this.binFiles.find(({ path }) => path === binFilepath); const storageSlotFilepath = abiFile.path.replace("-abi.json", "-storage_slots.json"); const relatedStorageSlotsFile = this.storageSlotsFiles.find( ({ path }) => path === storageSlotFilepath ); if (!relatedBinFile) { validateBinFile({ abiFilepath: abiFile.path, binExists: !!relatedBinFile, binFilepath, programType }); } const abi = new Abi({ filepath: abiFile.path, rawContents: JSON.parse(abiFile.contents), hexlifiedBinContents: relatedBinFile?.contents, storageSlotsContents: relatedStorageSlotsFile?.contents, outputDir, programType }); return abi; }); this.files = this.getAssembledFiles({ programType }); } getAssembledFiles(params) { const { abis, outputDir } = this; const { programType } = params; switch (programType) { case "contract" /* CONTRACT */: return assembleContracts({ abis, outputDir }); case "script" /* SCRIPT */: return assembleScripts({ abis, outputDir }); case "predicate" /* PREDICATE */: return assemblePredicates({ abis, outputDir }); default: throw new import_errors8.FuelError( import_errors8.ErrorCode.INVALID_INPUT_PARAMETERS, `Invalid Typegen programType: ${programType}. Must be one of ${Object.values( ProgramTypeEnum )}` ); } } }; // src/utils/collectBinFilePaths.ts var import_utils2 = require("@fuel-ts/utils"); var import_fs = require("fs"); var collectBinFilepaths = (params) => { const { filepaths, programType } = params; const binFiles = filepaths.map((abiFilepath) => { const binFilepath = abiFilepath.replace("-abi.json", ".bin"); const binExists = (0, import_fs.existsSync)(binFilepath); validateBinFile({ abiFilepath, binFilepath, binExists, programType }); const bin = { path: binFilepath, contents: (0, import_utils2.hexlify)((0, import_fs.readFileSync)(binFilepath)) }; return bin; }); return binFiles; }; // src/utils/collectStorageSlotsFilePaths.ts var import_fs2 = require("fs"); var collectStorageSlotsFilepaths = (params) => { const { filepaths, programType } = params; const storageSlotsFiles = []; if (programType !== "contract" /* CONTRACT */) { return storageSlotsFiles; } filepaths.forEach((abiFilepath) => { const storageSlotsFilepath = abiFilepath.replace("-abi.json", "-storage_slots.json"); const storageSlotsExists = (0, import_fs2.existsSync)(storageSlotsFilepath); if (storageSlotsExists) { const storageSlots = { path: storageSlotsFilepath, contents: (0, import_fs2.readFileSync)(storageSlotsFilepath, "utf-8") }; storageSlotsFiles.push(storageSlots); } }); return storageSlotsFiles; }; // src/runTypegen.ts function runTypegen(params) { const { cwd, inputs, output, silent, programType, filepaths: inputFilepaths } = params; const cwdBasename = (0, import_path4.basename)(cwd); function log(.