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);