|
|
|
@ -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' }) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|