/ hc-contract / scripts / build.js
build.js
  1  import { CompilerHttpNode } from "@aeternity/aepp-sdk";
  2  import JSONbig from "json-bigint";
  3  import aecalldata from "@aeternity/aepp-calldata";
  4  import fs from "fs";
  5  import path from "path";
  6  import { fileURLToPath } from 'url';
  7  
  8  const BUILD_DIR = "build";
  9  
 10  const __filename = fileURLToPath(import.meta.url);
 11  const __dirname = path.dirname(__filename);
 12  const projectRoot = path.resolve(__dirname, '..');
 13  
 14  const JSONbigConfigured = JSONbig({
 15    useNativeBigInt: true,
 16    storeAsString: false,
 17    alwaysParseAsBig: true,
 18  });
 19  
 20  export function toJSON(s) {
 21    return JSONbigConfigured.stringify(s, null, 2);
 22  };
 23  
 24  // --- Main Build Function ---
 25  async function buildContract(contractSourcePath) {
 26    console.log(`Starting build for: ${contractSourcePath}`);
 27  
 28    if (!contractSourcePath) {
 29      console.error("Error: Contract source file path is required.");
 30      console.log("Usage: node scripts/build.js <path/to/Contract.aes>");
 31      process.exit(1);
 32    }
 33  
 34    const absoluteContractPath = path.resolve(projectRoot, contractSourcePath);
 35    const buildDirPath = path.resolve(projectRoot, BUILD_DIR);
 36  
 37    try {
 38      // 1. Ensure contract source file exists
 39      if (!fs.existsSync(absoluteContractPath)) {
 40        throw new Error(`Contract source file not found: ${absoluteContractPath}`);
 41      }
 42      console.log(`Found contract source: ${absoluteContractPath}`);
 43  
 44      // 2. Ensure build directory exists
 45      if (!fs.existsSync(buildDirPath)) {
 46        console.log(`Creating build directory: ${buildDirPath}`);
 47        fs.mkdirSync(buildDirPath, { recursive: true });
 48      }
 49  
 50      // 5. Initialize SDK and Contract (compiles the contract)
 51      console.log("Initializing SDK...");
 52  
 53      const contractName = path.parse(contractSourcePath).name;
 54      const COMPILER_URL = "http://localhost:3080"
 55      const compiler = new CompilerHttpNode(COMPILER_URL);
 56      const compiled = await compiler.compile(absoluteContractPath);
 57      // console.log('compiled:', compiled)
 58      const encoder = new aecalldata.AciContractCallEncoder(compiled.aci);
 59      const initCallData = [];
 60  
 61      console.log("encoding: ", contractName, initCallData);
 62      console.log(JSON.stringify(compiled.aci[3], null, 4));
 63  
 64      const initCallDataEnc = encoder.encodeCall(
 65        contractName,
 66        "init",
 67        initCallData
 68      );
 69  
 70      console.log("initCallDataEnc: ", initCallDataEnc);
 71  
 72      // 7. Determine output file path
 73      const outputFilename = `${contractName}.json`;
 74      const outputFilePath = path.join(buildDirPath, outputFilename);
 75  
 76      const out = {
 77        aci: compiled.aci,
 78        aciStr: toJSON(compiled.aci),
 79        init: {
 80          abi_version: 3n,
 81          vm_version: 8n,
 82          amount: 0n,
 83          nonce: BigInt(0n),
 84          code: compiled.bytecode,
 85          call_data: initCallDataEnc,
 86        },
 87        meta: {
 88          name: contractName,
 89        },
 90      };
 91  
 92      fs.writeFileSync(outputFilePath, toJSON(out, null, 2));
 93      console.log(`✅ JSON successfully written to: ${outputFilePath}`);
 94  
 95    } catch (error) {
 96      console.error("\n--- Build Failed ---");
 97      console.error(error.message);
 98      if (error.message.includes('compile error')) {
 99        console.error("Compilation Error Details:", error);
100      } else if (error.message.includes('Failed to fetch')) {
101        console.error("Network or File System Error Details:", error);
102      }
103      console.error("--------------------\n");
104      process.exit(1);
105    }
106  }
107  
108  const contractArg = process.argv[2]; // Get the contract path from the command line argument
109  buildContract(contractArg);