@@ -17,7 +17,7 @@ const generatedContractComment = `
1717` ;
1818
1919const DEPLOYMENTS_DIR = "./ignition/deployments" ;
20- // const ARTIFACTS_DIR = "./artifacts";
20+ const ARTIFACTS_DIR = "./artifacts" ;
2121
2222function getDirectories ( path : string ) {
2323 return fs
@@ -26,83 +26,140 @@ function getDirectories(path: string) {
2626 . map ( dirent => dirent . name ) ;
2727}
2828
29- function getContractFilenames ( path : string ) {
30- return fs
31- . readdirSync ( path , { withFileTypes : true } )
32- . filter ( dirent => dirent . isFile ( ) && dirent . name . endsWith ( ".json" ) )
33- . map ( dirent => dirent . name . split ( "." ) [ 0 ] ) ;
29+ function getActualSourcesForContract ( sources : Record < string , any > , contractName : string ) {
30+ for ( const sourcePath of Object . keys ( sources ) ) {
31+ const sourceName = sourcePath . split ( "/" ) . pop ( ) ?. split ( ".sol" ) [ 0 ] ;
32+ if ( sourceName === contractName ) {
33+ const contractContent = sources [ sourcePath ] . content as string ;
34+ const regex = / c o n t r a c t \s + ( \w + ) \s + i s \s + ( [ ^ { } ] + ) \{ / ;
35+ const match = contractContent . match ( regex ) ;
36+
37+ if ( match ) {
38+ const inheritancePart = match [ 2 ] ;
39+ // Split the inherited contracts by commas to get the list of inherited contracts
40+ const inheritedContracts = inheritancePart . split ( "," ) . map ( contract => `${ contract . trim ( ) } .sol` ) ;
41+
42+ return inheritedContracts ;
43+ }
44+ return [ ] ;
45+ }
46+ }
47+ return [ ] ;
48+ }
49+
50+ function getInheritedFunctions (
51+ sources : Record < string , any > ,
52+ contractName : string ,
53+ compiledContracts : Record < string , any > ,
54+ ) {
55+ const actualSources = getActualSourcesForContract ( sources , contractName ) ;
56+ const inheritedFunctions = { } as Record < string , any > ;
57+
58+ for ( const sourceContractName of actualSources ) {
59+ const sourcePath = Object . keys ( sources ) . find ( key => key . includes ( `/${ sourceContractName } ` ) ) ;
60+
61+ if ( sourcePath ) {
62+ // Extract the actual contract name without .sol extension
63+ const cleanContractName = sourceContractName . replace ( ".sol" , "" ) ;
64+
65+ // Try to find the contract in the compiled output
66+ const compiledContract = compiledContracts [ sourcePath ] ?. [ cleanContractName ] ;
67+
68+ if ( compiledContract ?. abi ) {
69+ for ( const functionAbi of compiledContract . abi ) {
70+ if ( functionAbi . type === "function" ) {
71+ inheritedFunctions [ functionAbi . name ] = sourcePath ;
72+ }
73+ }
74+ }
75+ }
76+ }
77+
78+ return inheritedFunctions ;
3479}
3580
36- // function getActualSourcesForContract(sources: Record<string, any>, contractName: string) {
37- // for (const sourcePath of Object.keys(sources)) {
38- // const sourceName = sourcePath.split("/").pop()?.split(".sol")[0];
39- // if (sourceName === contractName) {
40- // const contractContent = sources[sourcePath].content as string;
41- // const regex = /contract\s+(\w+)\s+is\s+([^{}]+)\{/;
42- // const match = contractContent.match(regex);
43-
44- // if (match) {
45- // const inheritancePart = match[2];
46- // // Split the inherited contracts by commas to get the list of inherited contracts
47- // const inheritedContracts = inheritancePart.split(",").map(contract => `${contract.trim()}.sol`);
48-
49- // return inheritedContracts;
50- // }
51- // return [];
52- // }
53- // }
54- // return [];
55- // }
56-
57- // function getInheritedFunctions(sources: Record<string, any>, contractName: string) {
58- // const actualSources = getActualSourcesForContract(sources, contractName);
59- // const inheritedFunctions = {} as Record<string, any>;
60-
61- // for (const sourceContractName of actualSources) {
62- // const sourcePath = Object.keys(sources).find(key => key.includes(`/${sourceContractName}`));
63- // if (sourcePath) {
64- // const sourceName = sourcePath?.split("/").pop()?.split(".sol")[0];
65- // const { abi } = JSON.parse(fs.readFileSync(`${ARTIFACTS_DIR}/${sourcePath}/${sourceName}.json`).toString());
66- // for (const functionAbi of abi) {
67- // if (functionAbi.type === "function") {
68- // inheritedFunctions[functionAbi.name] = sourcePath;
69- // }
70- // }
71- // }
72- // }
73-
74- // return inheritedFunctions;
75- // }
81+ function getDeploymentBlockNumbers ( journalPath : string ) : Record < string , number > {
82+ const blockNumbers : Record < string , number > = { } ;
83+
84+ if ( ! fs . existsSync ( journalPath ) ) {
85+ return blockNumbers ;
86+ }
87+
88+ const journalContent = fs . readFileSync ( journalPath , "utf-8" ) ;
89+ const lines = journalContent . split ( "\n" ) . filter ( line => line . trim ( ) ) ;
90+
91+ for ( const line of lines ) {
92+ try {
93+ const entry = JSON . parse ( line ) ;
94+ // Look for TRANSACTION_CONFIRM entries which contain deployment receipt info
95+ if ( entry . type === "TRANSACTION_CONFIRM" && entry . receipt ?. blockNumber && entry . futureId ) {
96+ blockNumbers [ entry . futureId ] = entry . receipt . blockNumber ;
97+ }
98+ } catch {
99+ // Skip invalid JSON lines
100+ continue ;
101+ }
102+ }
103+
104+ return blockNumbers ;
105+ }
76106
77107function getContractDataFromDeployments ( ) {
78108 if ( ! fs . existsSync ( DEPLOYMENTS_DIR ) ) {
79109 throw Error ( "At least one other deployment script should exist to generate an actual contract." ) ;
80110 }
81111 const output = { } as Record < string , any > ;
82- const chainDirectories = getDirectories ( DEPLOYMENTS_DIR ) ;
112+ for ( const dirName of getDirectories ( DEPLOYMENTS_DIR ) ) {
113+ const chainId = dirName . split ( "-" ) [ 1 ] ;
114+
115+ const arfifactsPath = `${ DEPLOYMENTS_DIR } /${ dirName } /artifacts` ;
116+ const journalPath = `${ DEPLOYMENTS_DIR } /${ dirName } /journal.jsonl` ;
117+
118+ // Get block numbers from journal
119+ const blockNumbers = getDeploymentBlockNumbers ( journalPath ) ;
83120
84- for ( const chainDirectory of chainDirectories ) {
85- const chainId = chainDirectory . split ( "-" ) [ 1 ] ;
121+ const fileNames = new Set < string > ( ) ;
122+
123+ for ( const fileName of fs . readdirSync ( arfifactsPath ) ) {
124+ const actualFile = fileName . split ( "." ) [ 0 ] ;
125+ fileNames . add ( actualFile ) ;
126+ }
86127
87128 const contracts = { } as Record < string , any > ;
88- for ( const contractFilename of getContractFilenames ( `${ DEPLOYMENTS_DIR } /${ chainDirectory } /artifacts` ) ) {
89- const { abi, contractName } = JSON . parse (
90- fs . readFileSync ( `${ DEPLOYMENTS_DIR } /${ chainDirectory } /artifacts/${ contractFilename } .json` ) . toString ( ) ,
91- ) ;
92- const deployedAddresses = JSON . parse (
93- fs . readFileSync ( `${ DEPLOYMENTS_DIR } /${ chainDirectory } /deployed_addresses.json` ) . toString ( ) ,
94- ) ;
95- const address = deployedAddresses [ contractFilename ] ;
96-
97- // const inheritedFunctions = metadata ? getInheritedFunctions(JSON.parse(metadata).sources, contractName) : {};
98- // TODO
99- const inheritedFunctions = { } ;
100- // TODO
101- const receipt = {
102- blockNumber : 0 ,
129+
130+ for ( const fileName of fileNames ) {
131+ const JsonFilePath = `${ arfifactsPath } /${ fileName } .json` ;
132+ const JsonFileContent = fs . readFileSync ( JsonFilePath ) . toString ( ) ;
133+ const { abi, contractName, buildInfoId } = JSON . parse ( JsonFileContent ) ;
134+
135+ const ignitionBuildInfoPath = `${ DEPLOYMENTS_DIR } /${ dirName } /build-info/${ buildInfoId } .json` ;
136+ const ignitionBuildInfo = JSON . parse ( fs . readFileSync ( ignitionBuildInfoPath ) . toString ( ) ) ;
137+ const { input } = ignitionBuildInfo ;
138+
139+ const artifactsBuildInfoPath = `${ ARTIFACTS_DIR } /build-info/${ buildInfoId } .output.json` ;
140+ let compiledContracts = { } ;
141+ if ( fs . existsSync ( artifactsBuildInfoPath ) ) {
142+ const artifactsBuildInfo = JSON . parse ( fs . readFileSync ( artifactsBuildInfoPath ) . toString ( ) ) ;
143+ compiledContracts = artifactsBuildInfo . output ?. contracts || { } ;
144+ }
145+
146+ const inheritedFunctions = getInheritedFunctions ( input . sources , contractName , compiledContracts ) ;
147+
148+ const deployedAddresses = fs . readFileSync ( `${ DEPLOYMENTS_DIR } /${ dirName } /deployed_addresses.json` ) . toString ( ) ;
149+ const deployedAddressesJson = JSON . parse ( deployedAddresses ) ;
150+ const address = deployedAddressesJson [ fileName ] ;
151+
152+ // Get deployment block number from journal (futureId matches fileName)
153+ const deploymentBlock = blockNumbers [ fileName ] ;
154+
155+ contracts [ contractName ] = {
156+ address,
157+ abi,
158+ inheritedFunctions,
159+ ...( deploymentBlock !== undefined && { deployedOnBlock : deploymentBlock } ) ,
103160 } ;
104- contracts [ contractName ] = { address, abi, inheritedFunctions, deployedOnBlock : receipt ?. blockNumber } ;
105161 }
162+
106163 output [ chainId ] = contracts ;
107164 }
108165 return output ;
0 commit comments