@@ -15,36 +15,47 @@ import { loadManifest, saveManifest } from "./manifest.js";
1515const execAsync = promisify ( exec ) ;
1616
1717export class AlkanesCompiler {
18- private tempDir : string = ".labcoat" ;
18+ private baseDir : string ;
19+
20+ constructor ( customTempDir ?: string ) {
21+ // Allow override via arg or environment
22+ this . baseDir = customTempDir || process . env . TMP_BUILD_DIR || ".labcoat" ;
23+ }
1924
2025 async compile (
2126 contractName : string ,
2227 sourceCode : string
2328 ) : Promise < { wasmBuffer : Buffer ; abi : AlkanesABI } | void > {
29+ // Each compile gets its own subdirectory
30+ const buildId = `build_${ Date . now ( ) . toString ( 36 ) } ` ;
31+ const tempDir = path . join ( this . baseDir , buildId ) ;
32+
2433 try {
25- await this . createProject ( sourceCode ) ;
34+ await this . createProject ( tempDir , sourceCode ) ;
35+
36+ console . log ( `🧱 Building in ${ tempDir } ` ) ;
2637
27- const { stderr } = await execAsync (
38+ const { stdout , stderr } = await execAsync (
2839 `cargo clean && cargo build --target=wasm32-unknown-unknown --release` ,
29- { cwd : this . tempDir }
40+ { cwd : tempDir }
3041 ) ;
3142
32- if ( stderr ) {
33- console . warn ( "Build warnings:" , stderr ) ;
34- }
43+ if ( stderr ?. trim ( ) ) console . warn ( "⚠️ Build warnings:" , stderr ) ;
44+ if ( stdout ?. trim ( ) ) console . log ( stdout ) ;
3545
3646 // Read compiled WASM
3747 const wasmPath = path . join (
38- this . tempDir ,
48+ tempDir ,
3949 "target" ,
4050 "wasm32-unknown-unknown" ,
4151 "release" ,
4252 "alkanes_contract.wasm"
4353 ) ;
44- const wasmBuffer = await fs . readFile ( wasmPath ) ;
4554
55+ const wasmBuffer = await fs . readFile ( wasmPath ) ;
4656 const abi = await this . parseABI ( sourceCode ) ;
4757
58+ // Output files
4859 const buildDir = "./build" ;
4960 await fs . mkdir ( buildDir , { recursive : true } ) ;
5061
@@ -54,6 +65,7 @@ export class AlkanesCompiler {
5465 await fs . writeFile ( abiPath , JSON . stringify ( abi , null , 2 ) ) ;
5566 await fs . writeFile ( wasmOutPath , await gzipWasm ( wasmBuffer ) ) ;
5667
68+ // Manifest update
5769 const manifest = await loadManifest ( ) ;
5870 manifest [ contractName ] = {
5971 ...( manifest [ contractName ] || { } ) ,
@@ -70,23 +82,26 @@ export class AlkanesCompiler {
7082 return { wasmBuffer, abi } ;
7183 } catch ( error ) {
7284 if ( error instanceof Error ) {
85+ console . error ( `❌ Compilation failed: ${ error . message } ` ) ;
7386 throw new Error ( `Compilation failed: ${ error . message } ` ) ;
7487 }
88+ } finally {
89+ // Clean up temp folder
90+ await fs . rm ( tempDir , { recursive : true , force : true } ) . catch ( ( ) => { } ) ;
7591 }
7692 }
7793
78- private async createProject ( sourceCode : string ) {
79- await fs . mkdir ( this . tempDir , { recursive : true } ) ;
80- await fs . mkdir ( path . join ( this . tempDir , "src" ) , { recursive : true } ) ;
81- await fs . writeFile ( path . join ( this . tempDir , "Cargo.toml" ) , cargoTemplate ) ;
82- await fs . writeFile ( path . join ( this . tempDir , "src" , "lib.rs" ) , sourceCode ) ;
94+ private async createProject ( tempDir : string , sourceCode : string ) {
95+ await fs . mkdir ( tempDir , { recursive : true } ) ;
96+ await fs . mkdir ( path . join ( tempDir , "src" ) , { recursive : true } ) ;
97+ await fs . writeFile ( path . join ( tempDir , "Cargo.toml" ) , cargoTemplate ) ;
98+ await fs . writeFile ( path . join ( tempDir , "src" , "lib.rs" ) , sourceCode ) ;
8399 }
84100
85101 public async parseABI ( sourceCode : string ) : Promise < AlkanesABI > {
86102 const methods : AlkanesMethod [ ] = [ ] ;
87103 const opcodes : Record < string , number > = { } ;
88104
89- // Match enum variants
90105 const messageRegex =
91106 / # \[ o p c o d e \( ( \d + ) \) \] (?: \s * # \[ r e t u r n s \( ( [ ^ ) ] + ) \) \] ) ? \s * ( [ A - Z a - z _ ] [ A - Z a - z 0 - 9 _ ] * ) \s * (?: \{ ( [ ^ } ] * ) \} ) ? / gm;
92107
@@ -115,16 +130,15 @@ export class AlkanesCompiler {
115130 opcodes [ variantName ] = opcodeNum ;
116131 }
117132
118- // Parse struct name(s)
119133 const structRegex = / p u b \s + s t r u c t \s + ( \w + ) / g;
120134 const structNames : string [ ] = [ ] ;
121135 let structMatch : RegExpExecArray | null ;
122136 while ( ( structMatch = structRegex . exec ( sourceCode ) ) !== null ) {
123137 structNames . push ( structMatch [ 1 ] ) ;
124138 }
139+
125140 const name = structNames . length > 0 ? structNames [ 0 ] : "UnknownContract" ;
126141
127- // Parse storage pointers
128142 const storage : StorageKey [ ] = [ ] ;
129143 const storageRegex = / S t o r a g e P o i n t e r : : f r o m _ k e y w o r d \( " ( [ ^ " ] + ) " \) / g;
130144 let storageMatch : RegExpExecArray | null ;
0 commit comments