UNPKG

@axelar-network/axelar-cgp-sui

Version:
212 lines 9.67 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDefinedSuiVersion = exports.getInstalledSuiVersion = void 0; exports.prepareMoveBuild = prepareMoveBuild; exports.getContractBuild = getContractBuild; exports.writeInterchainToken = writeInterchainToken; exports.removeFile = removeFile; exports.addFile = addFile; exports.updateMoveToml = updateMoveToml; exports.copyMovePackage = copyMovePackage; exports.newInterchainToken = newInterchainToken; exports.getLocalDependencies = getLocalDependencies; exports.getDeploymentOrder = getDeploymentOrder; const child_process_1 = require("child_process"); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const smol_toml_1 = __importDefault(require("smol-toml")); /** * Prepare a move build by creating a temporary directory to store the compiled move code * @returns {tmpdir: string, rmTmpDir: () => void} * - tmpdir is the path to the temporary directory * - rmTmpDir is a function to remove the temporary directory */ function prepareMoveBuild(tmpDir) { const tmpdir = fs_1.default.mkdtempSync(path_1.default.join(tmpDir, '.move-build-')); const rmTmpDir = () => fs_1.default.rmSync(tmpdir, { recursive: true }); return { tmpdir, rmTmpDir, }; } const getInstalledSuiVersion = () => { const suiVersion = (0, child_process_1.execSync)('sui --version').toString().trim(); return parseVersion(suiVersion); }; exports.getInstalledSuiVersion = getInstalledSuiVersion; const getDefinedSuiVersion = () => { const version = fs_1.default.readFileSync(`${__dirname}/../../version.json`, 'utf8'); const suiVersion = JSON.parse(version).SUI_VERSION; return parseVersion(suiVersion); }; exports.getDefinedSuiVersion = getDefinedSuiVersion; const parseVersion = (version) => { const versionMatch = version.match(/\d+\.\d+\.\d+/); return versionMatch === null || versionMatch === void 0 ? void 0 : versionMatch[0]; }; function getContractBuild(packageName, moveDir) { const emptyPackageId = '0x0'; updateMoveToml(packageName, emptyPackageId, moveDir); const { tmpdir, rmTmpDir } = prepareMoveBuild(path_1.default.dirname(moveDir)); try { const { modules, dependencies, digest } = JSON.parse((0, child_process_1.execSync)(`sui move build --dump-bytecode-as-base64 --path ${path_1.default.join(moveDir, packageName)} --install-dir ${tmpdir}`, { encoding: 'utf-8', stdio: 'pipe', })); return { modules, dependencies, digest }; } finally { rmTmpDir(); } } function writeInterchainToken(moveDir, options) { const templateFilePath = `${moveDir}/interchain_token/sources/interchain_token.move`; const templateContent = fs_1.default.readFileSync(templateFilePath, 'utf8'); const { filePath, content } = newInterchainToken(templateFilePath, options); fs_1.default.writeFileSync(filePath, content, 'utf8'); return { templateFilePath, filePath, templateContent }; } function removeFile(filePath) { fs_1.default.rmSync(filePath); } function addFile(filePath, content) { fs_1.default.writeFileSync(filePath, content, 'utf8'); } function updateMoveToml(packageName, packageId, moveDir = `${__dirname}/../../move`, prepToml = undefined) { // Path to the Move.toml file for the package const movePath = `${moveDir}/${packageName}/Move.toml`; // Check if the Move.toml file exists if (!fs_1.default.existsSync(movePath)) { throw new Error(`Move.toml file not found for given path: ${movePath}`); } // Read the Move.toml file const moveRaw = fs_1.default.readFileSync(movePath, 'utf8'); // Parse the Move.toml file as JSON // eslint-disable-next-line @typescript-eslint/no-explicit-any let moveJson = smol_toml_1.default.parse(moveRaw); // Update the published-at field under the package section e.g. published-at = "0x01" moveJson.package['published-at'] = packageId; // Update the package address under the addresses section e.g. gas_service = "0x1" moveJson.addresses[packageName] = packageId; if (prepToml) { moveJson = prepToml(moveJson); } fs_1.default.writeFileSync(movePath, smol_toml_1.default.stringify(moveJson)); } function copyMovePackage(packageName, fromDir, toDir) { if (fromDir == null) { fromDir = `${__dirname}/../../move`; } if (fs_1.default.existsSync(`${toDir}/${packageName}`)) { fs_1.default.rmSync(`${toDir}/${packageName}`, { recursive: true }); } fs_1.default.cpSync(`${fromDir}/${packageName}`, `${toDir}/${packageName}`, { recursive: true }); } function newInterchainToken(templateFilePath, options) { let content = fs_1.default.readFileSync(templateFilePath, 'utf8'); const defaultFilePath = path_1.default.join(path_1.default.dirname(templateFilePath), `${options.symbol.toLowerCase()}.move`); const filePath = options.filePath || defaultFilePath; const structRegex = new RegExp(`struct\\s+Q\\s+has\\s+drop\\s+{}`, 'g'); // replace the module name with the token symbol in lowercase content = content.replace(/(module\s+)([^:]+)(::)([^{]+)/, `$1interchain_token$3${options.symbol.toLowerCase()}`); // replace the struct name with the token symbol in uppercase content = content.replace(structRegex, `struct ${options.symbol.toUpperCase()} has drop {}`); // replace the witness type with the token symbol in uppercase content = content.replace(/(fun\s+init\s*\()witness:\s*Q/, `$1witness: ${options.symbol.toUpperCase()}`); // replace the decimals with the given decimals content = content.replace(/(witness,\s*)(\d+)/, `$1${options.decimals}`); // replace the symbol with the given symbol content = content.replace(/(b")(Q)(")/, `$1${options.symbol.toUpperCase()}$3`); // replace the name with the given name content = content.replace(/(b")(Quote)(")/, `$1${options.name}$3`); // replace the generic type with the given symbol content = content.replace(/<Q>/g, `<${options.symbol.toUpperCase()}>`); return { filePath, content, }; } /** * Get the local dependencies of a package from the Move.toml file. * @param packageName The name of the package. * @param baseMoveDir The parent directory of the Move.toml file. * @returns An array of objects containing the name and path of the local dependencies. */ function getLocalDependencies(packageName, baseMoveDir) { const movePath = `${baseMoveDir}/${packageName}/Move.toml`; if (!fs_1.default.existsSync(movePath)) { throw new Error(`Move.toml file not found for given path: ${movePath}`); } // eslint-disable-next-line @typescript-eslint/no-explicit-any const { dependencies } = smol_toml_1.default.parse(fs_1.default.readFileSync(movePath, 'utf8')); const localDependencies = Object.keys(dependencies).filter((key) => dependencies[key].local); return localDependencies.map((key) => ({ name: key, path: `${baseMoveDir}/${path_1.default.resolve(path_1.default.dirname(movePath), dependencies[key].local)}`, directory: dependencies[key].local.split('/').slice(-1)[0], })); } /** * Determines the deployment order of Move packages based on their dependencies. * * @param packageDir - The directory of the main package to start the dependency resolution from. * @param baseMoveDir - The base directory where all Move packages are located. * @returns An array of package directory names in the order they should be deployed. * The array is sorted such that packages with no dependencies come first, * followed by packages whose dependencies have already appeared in the array. * * @description * This function performs the following steps: * 1. Recursively builds a dependency map starting from the given package. * 2. Performs a topological sort on the dependency graph. * 3. Returns the sorted list of package directories. * * The function handles circular dependencies and will include each package only once in the output. * If a package has multiple dependencies, it will appear in the list after all its dependencies. * * @example * const deploymentOrder = getDeploymentOrder('myPackage', '/path/to/move'); * console.log(deploymentOrder); * Might output: ['dependency1', 'dependency2', 'myPackage'] */ function getDeploymentOrder(packageDir, baseMoveDir) { const dependencyMap = {}; function recursiveDependencies(pkgDir) { if (dependencyMap[pkgDir]) { return; } const dependencies = getLocalDependencies(pkgDir, baseMoveDir); dependencyMap[pkgDir] = { name: pkgDir, directory: pkgDir, path: `${baseMoveDir}/${pkgDir}`, dependencies: dependencies.map((dep) => dep.directory), }; for (const dependency of dependencies) { recursiveDependencies(dependency.directory); } } recursiveDependencies(packageDir); // Topological sort const sorted = []; const visited = {}; function visit(name) { if (visited[name]) { return; } visited[name] = true; const node = dependencyMap[name]; for (const depName of node.dependencies) { visit(depName); } sorted.push(node); } for (const name in dependencyMap) { visit(name); } return sorted.map((dep) => dep.directory); } //# sourceMappingURL=node-utils.js.map