diff --git a/plugins/hardhat.plugin.js b/plugins/hardhat.plugin.js index 6342570..33fce48 100644 --- a/plugins/hardhat.plugin.js +++ b/plugins/hardhat.plugin.js @@ -98,6 +98,7 @@ task("coverage", "Generates a code coverage report for tests") .addOptionalParam("solcoverjs", ui.flags.solcoverjs, "", types.string) .addOptionalParam('temp', ui.flags.temp, "", types.string) .addFlag('matrix', ui.flags.testMatrix) + .addFlag('abi', ui.flags.abi) .setAction(async function(args, env){ const API = require('./../lib/api'); @@ -141,6 +142,16 @@ task("coverage", "Generates a code coverage report for tests") } env.hardhatArguments = Object.assign(env.hardhatArguments, flags) + // =========================== + // Generate abi diff component + // (This flag only useful within codecheck context) + // =========================== + if (args.abi){ + measureCoverage = false; + await nomiclabsUtils.generateHumanReadableAbiList(env, api, TASK_COMPILE); + return; + } + // ================ // Instrumentation // ================ diff --git a/plugins/resources/nomiclabs.ui.js b/plugins/resources/nomiclabs.ui.js index 7027095..bf97a4c 100644 --- a/plugins/resources/nomiclabs.ui.js +++ b/plugins/resources/nomiclabs.ui.js @@ -12,6 +12,9 @@ class PluginUI extends UI { testMatrix: `Generate a json object which maps which unit tests hit which lines of code.`, + abi: `Generate a json object which can be used to produce a unified diff of your ` + + `contracts public interface between two commits.`, + solcoverjs: `Relative path from working directory to config. ` + `Useful for monorepo packages that share settings.`, diff --git a/plugins/resources/nomiclabs.utils.js b/plugins/resources/nomiclabs.utils.js index 59a671c..21df995 100644 --- a/plugins/resources/nomiclabs.utils.js +++ b/plugins/resources/nomiclabs.utils.js @@ -190,7 +190,7 @@ async function getAllArtifacts(env){ const all = []; const qualifiedNames = await env.artifacts.getArtifactPaths(); for (const name of qualifiedNames){ - all.push(await env.artifacts.readArtifact(name)); + all.push(require(name)); } return all; } @@ -203,9 +203,9 @@ async function getAllArtifacts(env){ * @param {HRE} env * @param {SolidityCoverageAPI} api */ -async function generateHumanReadableAbiList(env, api){ +async function generateHumanReadableAbiList(env, api, TASK_COMPILE){ await env.run(TASK_COMPILE); - const _artifacts = getAllArtifacts(env); + const _artifacts = await getAllArtifacts(env); const list = api.abiUtils.generateHumanReadableAbiList(_artifacts) api.saveHumanReadableAbis(list); } @@ -263,6 +263,7 @@ module.exports = { getTestFilePaths, setNetworkFrom, collectTestMatrixData, - getAllArtifacts + getAllArtifacts, + generateHumanReadableAbiList } diff --git a/plugins/resources/truffle.utils.js b/plugins/resources/truffle.utils.js index 13997e4..f1c9bd3 100644 --- a/plugins/resources/truffle.utils.js +++ b/plugins/resources/truffle.utils.js @@ -63,7 +63,7 @@ function getAllArtifacts(config){ * @param {SolidityCoverageAPI} api */ async function generateHumanReadableAbiList(config, truffle, api){ - await truffle.compile(config); + await truffle.contracts.compile(config); const _artifacts = getAllArtifacts(config); const list = api.abiUtils.generateHumanReadableAbiList(_artifacts) api.saveHumanReadableAbis(list); @@ -268,5 +268,6 @@ module.exports = { loadLibrary, normalizeConfig, filteredLogger, - collectTestMatrixData + collectTestMatrixData, + generateHumanReadableAbiList } diff --git a/plugins/truffle.plugin.js b/plugins/truffle.plugin.js index 949077d..66ae98d 100644 --- a/plugins/truffle.plugin.js +++ b/plugins/truffle.plugin.js @@ -30,9 +30,18 @@ async function plugin(config){ truffle = truffleUtils.loadLibrary(config); api = new API(utils.loadSolcoverJS(config)); - truffleUtils.setNetwork(config, api); + // =========================== + // Generate abi diff component + // (This flag only useful within codecheck context) + // =========================== + if (config.abi){ + await truffleUtils.generateHumanReadableAbiList(config, truffle, api); + return; + } // Server launch + truffleUtils.setNetwork(config, api); + const client = api.client || truffle.ganache; const address = await api.ganache(client); const accountsRequest = await utils.getAccountsGanache(api.server.provider); diff --git a/test/units/hardhat/flags.js b/test/units/hardhat/flags.js index 6127e1a..c3c99d5 100644 --- a/test/units/hardhat/flags.js +++ b/test/units/hardhat/flags.js @@ -191,5 +191,38 @@ describe('Hardhat Plugin: command line options', function() { assert.deepEqual(producedMatrix, expectedMatrix); }); + + it('--abi', async function(){ + const expected = [ + { + "contractName": "Migrations", + "humanReadableAbiList": [ + "function last_completed_migration() view returns (uint256)", + "function owner() view returns (address)", + "function setCompleted(uint256) nonpayable", + "function upgrade(address) nonpayable" + ] + }, + { + "contractName": "Simple", + "humanReadableAbiList": [ + "function getX() view returns (uint256)", + "function test(uint256) nonpayable" + ] + } + ]; + + const taskArgs = { + abi: true + } + mock.install('Simple', 'simple.js', solcoverConfig); + mock.hardhatSetupEnv(this); + + await this.env.run("coverage", taskArgs); + + const outputPath = path.join(process.cwd(), 'humanReadableAbis.json'); + const output = require(outputPath); + assert.deepEqual(output, expected); + }) }); diff --git a/test/units/truffle/flags.js b/test/units/truffle/flags.js index e073fc3..234f186 100644 --- a/test/units/truffle/flags.js +++ b/test/units/truffle/flags.js @@ -275,5 +275,34 @@ describe('Truffle Plugin: command line options', function() { assert.deepEqual(producedMatrix, expectedMatrix); process.env.TRUFFLE_TEST = false; }); + + it('--abi', async function(){ + const expected = [ + { + "contractName": "Migrations", + "humanReadableAbiList": [ + "function last_completed_migration() view returns (uint256)", + "function owner() view returns (address)", + "function setCompleted(uint256) nonpayable", + "function upgrade(address) nonpayable" + ] + }, + { + "contractName": "Simple", + "humanReadableAbiList": [ + "function getX() view returns (uint256)", + "function test(uint256) nonpayable" + ] + } + ]; + + truffleConfig.abi = true; + mock.install('Simple', 'simple.js', solcoverConfig); + await plugin(truffleConfig); + + const outputPath = path.join(process.cwd(), mock.pathToTemp('./humanReadableAbis.json')); + const output = require(outputPath); + assert.deepEqual(output, expected); + }) });