From 5b177de77018b0319c0fc71c8209aa2e4f57b876 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Sat, 14 Jan 2023 10:44:55 +0100 Subject: [PATCH] fix foundry --- libs/remixd/src/services/foundryClient.ts | 102 ++++++++++++++-------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/libs/remixd/src/services/foundryClient.ts b/libs/remixd/src/services/foundryClient.ts index aa4e42f4c1..58f259ceb6 100644 --- a/libs/remixd/src/services/foundryClient.ts +++ b/libs/remixd/src/services/foundryClient.ts @@ -15,12 +15,12 @@ export class FoundryClient extends PluginClient { buildPath: string cachePath: string - constructor (private readOnly = false) { + constructor(private readOnly = false) { super() this.methods = ['compile', 'sync'] } - setWebSocket (websocket: WS): void { + setWebSocket(websocket: WS): void { this.websocket = websocket this.websocket.addEventListener('close', () => { this.warnlog = false @@ -28,14 +28,35 @@ export class FoundryClient extends PluginClient { }) } - sharedFolder (currentSharedFolder: string): void { + sharedFolder(currentSharedFolder: string): void { this.currentSharedFolder = currentSharedFolder this.buildPath = utils.absolutePath('out', this.currentSharedFolder) this.cachePath = utils.absolutePath('cache', this.currentSharedFolder) - this.listenOnFoundryCompilation() + if (fs.existsSync(this.buildPath) && fs.existsSync(this.cachePath)) { + this.listenOnFoundryCompilation() + } else { + console.log('Foundry out folder doesn\'t exist... waiting for the first compilation.') + this.listenOFoundryFolder() + } + } - compile (configPath: string) { + listenOFoundryFolder() { + try { + this.watcher = chokidar.watch(this.currentSharedFolder, { depth: 1, ignorePermissionErrors: true, ignoreInitial: true }) + // watch for new folders + this.watcher.on('addDir', (path) => { + if (fs.existsSync(this.buildPath) && fs.existsSync(this.cachePath)) { + this.buildPath = path + this.listenOnFoundryCompilation() + } + }) + } catch (e) { + console.log(e) + } + } + + compile(configPath: string) { return new Promise((resolve, reject) => { if (this.readOnly) { const errMsg = '[Foundry Compilation]: Cannot compile in read-only mode' @@ -62,48 +83,53 @@ export class FoundryClient extends PluginClient { }) } - private async processArtifact () { + private async processArtifact() { const folderFiles = await fs.readdir(this.buildPath) // "out" folder - const cache = JSON.parse(await fs.readFile(join(this.cachePath, 'solidity-files-cache.json'), { encoding: 'utf-8' })) - - // name of folders are file names - for (const file of folderFiles) { - const path = join(this.buildPath, file) // out/Counter.sol/ - const compilationResult = { - input: {}, - output: { - contracts: {}, - sources: {} - }, - solcVersion: null, - compilationTarget: null + if (!fs.existsSync(join(this.cachePath, 'solidity-files-cache.json'))) return + try { + const cache = JSON.parse(await fs.readFile(join(this.cachePath, 'solidity-files-cache.json'), { encoding: 'utf-8' })) + + // name of folders are file names + for (const file of folderFiles) { + const path = join(this.buildPath, file) // out/Counter.sol/ + const compilationResult = { + input: {}, + output: { + contracts: {}, + sources: {} + }, + solcVersion: null, + compilationTarget: null + } + await this.readContract(path, compilationResult, cache) + this.emit('compilationFinished', compilationResult.compilationTarget, { sources: compilationResult.input }, 'soljson', compilationResult.output, compilationResult.solcVersion) } - await this.readContract(path, compilationResult, cache) - this.emit('compilationFinished', compilationResult.compilationTarget, { sources: compilationResult.input } , 'soljson', compilationResult.output, compilationResult.solcVersion) - } - if (!this.warnlog) { - // @ts-ignore - this.call('terminal', 'log', { type: 'log', value: 'receiving compilation result from Foundry' }) - this.warnlog = true + if (!this.warnlog) { + // @ts-ignore + this.call('terminal', 'log', { type: 'log', value: 'receiving compilation result from Foundry' }) + this.warnlog = true + } + } catch (e) { + console.log(e) } } - listenOnFoundryCompilation () { - try { + listenOnFoundryCompilation() { + try { this.watcher = chokidar.watch(this.cachePath, { depth: 0, ignorePermissionErrors: true, ignoreInitial: true }) - + this.watcher.on('change', async (f: string) => this.processArtifact()) this.watcher.on('add', async (f: string) => this.processArtifact()) // process the artifact on activation setTimeout(() => this.processArtifact(), 1000) } catch (e) { console.log(e) - } + } } - async readContract (contractFolder, compilationResultPart, cache) { + async readContract(contractFolder, compilationResultPart, cache) { const files = await fs.readdir(contractFolder) - + for (const file of files) { const path = join(contractFolder, file) const content = await fs.readFile(path, { encoding: 'utf-8' }) @@ -111,13 +137,13 @@ export class FoundryClient extends PluginClient { } } - async feedContractArtifactFile (path, content, compilationResultPart, cache) { + async feedContractArtifactFile(path, content, compilationResultPart, cache) { const contentJSON = JSON.parse(content) const contractName = basename(path).replace('.json', '') - + const currentCache = cache.files[contentJSON.ast.absolutePath] if (!currentCache.artifacts[contractName]) return - + // extract source and version const metadata = contentJSON.metadata if (metadata.compiler && metadata.compiler.version) { @@ -141,7 +167,7 @@ export class FoundryClient extends PluginClient { console.log('\x1b[32m%s\x1b[0m', 'sources input not found, please update Foundry to the latest version.') } - + compilationResultPart.compilationTarget = contentJSON.ast.absolutePath // extract data if (!compilationResultPart.output['sources'][contentJSON.ast.absolutePath]) compilationResultPart.output['sources'][contentJSON.ast.absolutePath] = {} @@ -163,10 +189,10 @@ export class FoundryClient extends PluginClient { } } - async sync () { + async sync() { console.log('syncing from Foundry') this.processArtifact() // @ts-ignore - this.call('terminal', 'log', { type: 'log', value: 'synced with Foundry'}) + this.call('terminal', 'log', { type: 'log', value: 'synced with Foundry' }) } }