diff --git a/.changeset/empty-suns-kick.md b/.changeset/empty-suns-kick.md new file mode 100644 index 0000000000..b631295a6a --- /dev/null +++ b/.changeset/empty-suns-kick.md @@ -0,0 +1,5 @@ +--- +"@nomiclabs/hardhat-vyper": patch +--- + +Keep the parent exception when throwing because the compiler list download failed. diff --git a/.changeset/slimy-plums-reply.md b/.changeset/slimy-plums-reply.md new file mode 100644 index 0000000000..fc613d7f7c --- /dev/null +++ b/.changeset/slimy-plums-reply.md @@ -0,0 +1,8 @@ +--- +"@nomicfoundation/hardhat-toolbox": patch +"hardhat": minor +--- + +Added support for writing scripts and tests as ES modules. + +To learn how to start using ESM with Hardhat read [this guide](https://hardhat.org/hardhat-runner/docs/advanced/using-esm). diff --git a/docs/src/content/hardhat-runner/docs/advanced/_dirinfo.yaml b/docs/src/content/hardhat-runner/docs/advanced/_dirinfo.yaml index d2d3246fac..6365297f03 100644 --- a/docs/src/content/hardhat-runner/docs/advanced/_dirinfo.yaml +++ b/docs/src/content/hardhat-runner/docs/advanced/_dirinfo.yaml @@ -11,3 +11,4 @@ order: - /flattening - href: /vscode-tests title: Running tests in VS Code + - /using-esm diff --git a/docs/src/content/hardhat-runner/docs/advanced/using-esm.md b/docs/src/content/hardhat-runner/docs/advanced/using-esm.md new file mode 100644 index 0000000000..291a4cf4f6 --- /dev/null +++ b/docs/src/content/hardhat-runner/docs/advanced/using-esm.md @@ -0,0 +1,132 @@ +# Using ES modules + +Node.js projects can use one of two module systems: CommonJS and ES Modules (ESM). Hardhat was designed mainly with CommonJS in mind, but in the last years adoption of ESM has been growing. + +This guide explains where you can use ESM in your Hardhat project and how to do it. + +## Hardhat support for ES modules + +You can write your scripts and tests as both CommonJS and ES modules. However, your Hardhat config, and any file imported by it, **must** be CommonJS modules. + +If your package uses ESM by default (that is, you have [`"type": "module"`](https://nodejs.org/api/packages.html#type) in your `package.json`), then your Hardhat config file must be named `hardhat.config.cjs`. + +Hardhat doesn't support [ESM in TypeScript projects](#esm-and-typescript-projects). + +## Using ES Modules in Hardhat + +The following sections explain how to use ES modules in new or existing Hardhat projects. + +### Starting an ESM-first Hardhat project + +If you want to start a Hardhat project that uses ES modules by default, first you have to initialize a Node.js project: + +::::tabsgroup{options="npm 7+,npm 6,yarn"} + +:::tab{value="npm 7+"} + +``` +npm init -y +``` + +::: + +:::tab{value="npm 6"} + +``` +npm init -y +``` + +::: + +:::tab{value="yarn"} + +``` +yarn init -y +``` + +::: + +:::: + +Open the `package.json` that was created and add a `"type": "module"` entry. This will make the project use ESM by default. + +After that, install Hardhat: + +::::tabsgroup{options="npm 7+,npm 6,yarn"} + +:::tab{value="npm 7+"} + +``` +npm install --save-dev hardhat +``` + +::: + +:::tab{value="npm 6"} + +``` +npm install --save-dev hardhat +``` + +::: + +:::tab{value="yarn"} + +``` +yarn add --dev hardhat +``` + +::: + +:::: + +and run `npx hardhat` to create a Hardhat project: + +``` +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +Welcome to Hardhat v2.13.0 + +? What do you want to do? … +▸ Create a JavaScript project + Create a TypeScript project (not available for ESM projects) + Create an empty hardhat.config.cjs + Quit +``` + +Select the `Create a JavaScript project` option. This will initialize a Hardhat project where the scripts and tests are ES modules, and where the configuration has a `.cjs` extension. + +### Migrating a project to ESM + +If you have an existing Hardhat project and you want to convert it into an ESM project, follow these steps: + +1. Edit your `package.json` and add a `"type": "module"` entry. +2. Rename your `hardhat.config.js` file to `hardhat.config.cjs`. +3. Migrate all your scripts and tests from CommonJS to ESM. Alternatively, you can rename them to have a `.cjs` extension instead of `.js`. + +### Adding ESM files to an existing Hardhat project + +It's also possible to write ESM scripts and tests without making your whole project ESM by default. To do this, just create your scripts and tests with an `.mjs` extension. + +## ESM and TypeScript projects + +At the moment, it's not possible to use ESM in TypeScript projects. + +Hardhat uses [`ts-node`](https://typestrong.org/ts-node/) to run TypeScript projects, which in turn relies on Node's loader hooks. This is all experimental and the current functionality is not enough for Hardhat's needs. + +If you need this feature, please let us know in [this issue](https://github.com/NomicFoundation/hardhat/issues/3385). + +## Learn more + +To learn more about ES modules in general, check these resources: + +- [Node.js docs](https://nodejs.org/api/packages.html) +- [ES modules: A cartoon deep-dive](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) +- The [Modules chapter](https://exploringjs.com/impatient-js/ch_modules.html) of "JavaScript for impatient programmers" diff --git a/package.json b/package.json index 2262e46ce0..a89b0422fb 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "@changesets/cli": "^2.16.0", "prettier": "2.4.1", "shelljs": "^0.8.5", - "typescript": "~4.5.2", + "typescript": "~4.7.4", "wsrun": "^5.2.2" }, "scripts": { diff --git a/packages/e2e/package.json b/packages/e2e/package.json index 497a6a489a..492cbb1ea0 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -37,7 +37,7 @@ "prettier": "2.4.1", "rimraf": "^3.0.2", "shelljs": "^0.8.5", - "ts-node": "^8.1.0", - "typescript": "~4.5.2" + "ts-node": "^10.8.0", + "typescript": "~4.7.4" } } diff --git a/packages/hardhat-chai-matchers/package.json b/packages/hardhat-chai-matchers/package.json index f9ac11228b..8cb795b7c6 100644 --- a/packages/hardhat-chai-matchers/package.json +++ b/packages/hardhat-chai-matchers/package.json @@ -58,8 +58,8 @@ "mocha": "^10.0.0", "prettier": "2.4.1", "rimraf": "^3.0.2", - "ts-node": "^8.1.0", - "typescript": "~4.5.2" + "ts-node": "^10.8.0", + "typescript": "~4.7.4" }, "peerDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.0", diff --git a/packages/hardhat-core/package.json b/packages/hardhat-core/package.json index 592cbfca94..15790c1c71 100644 --- a/packages/hardhat-core/package.json +++ b/packages/hardhat-core/package.json @@ -93,8 +93,8 @@ "rimraf": "^3.0.2", "sinon": "^9.0.0", "time-require": "^0.1.2", - "ts-node": "^8.1.0", - "typescript": "~4.5.2" + "ts-node": "^10.8.0", + "typescript": "~4.7.4" }, "dependencies": { "@ethersproject/abi": "^5.1.2", diff --git a/packages/hardhat-core/sample-projects/javascript-esm/LICENSE.md b/packages/hardhat-core/sample-projects/javascript-esm/LICENSE.md new file mode 100644 index 0000000000..c539a505b4 --- /dev/null +++ b/packages/hardhat-core/sample-projects/javascript-esm/LICENSE.md @@ -0,0 +1,11 @@ +# License + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. + +In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to [https://unlicense.org](https://unlicense.org) diff --git a/packages/hardhat-core/sample-projects/javascript-esm/README.md b/packages/hardhat-core/sample-projects/javascript-esm/README.md new file mode 100644 index 0000000000..e9dd5f3485 --- /dev/null +++ b/packages/hardhat-core/sample-projects/javascript-esm/README.md @@ -0,0 +1,13 @@ +# Sample Hardhat Project + +This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. + +Try running some of the following tasks: + +```shell +npx hardhat help +npx hardhat test +REPORT_GAS=true npx hardhat test +npx hardhat node +npx hardhat run scripts/deploy.js +``` diff --git a/packages/hardhat-core/sample-projects/javascript-esm/contracts/Lock.sol b/packages/hardhat-core/sample-projects/javascript-esm/contracts/Lock.sol new file mode 100644 index 0000000000..50935f61fd --- /dev/null +++ b/packages/hardhat-core/sample-projects/javascript-esm/contracts/Lock.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.9; + +// Uncomment this line to use console.log +// import "hardhat/console.sol"; + +contract Lock { + uint public unlockTime; + address payable public owner; + + event Withdrawal(uint amount, uint when); + + constructor(uint _unlockTime) payable { + require( + block.timestamp < _unlockTime, + "Unlock time should be in the future" + ); + + unlockTime = _unlockTime; + owner = payable(msg.sender); + } + + function withdraw() public { + // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal + // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); + + require(block.timestamp >= unlockTime, "You can't withdraw yet"); + require(msg.sender == owner, "You aren't the owner"); + + emit Withdrawal(address(this).balance, block.timestamp); + + owner.transfer(address(this).balance); + } +} diff --git a/packages/hardhat-core/sample-projects/javascript-esm/hardhat.config.cjs b/packages/hardhat-core/sample-projects/javascript-esm/hardhat.config.cjs new file mode 100644 index 0000000000..86913e7054 --- /dev/null +++ b/packages/hardhat-core/sample-projects/javascript-esm/hardhat.config.cjs @@ -0,0 +1,6 @@ +require("@nomicfoundation/hardhat-toolbox"); + +/** @type import('hardhat/config').HardhatUserConfig */ +module.exports = { + solidity: "0.8.17", +}; diff --git a/packages/hardhat-core/sample-projects/javascript-esm/scripts/deploy.js b/packages/hardhat-core/sample-projects/javascript-esm/scripts/deploy.js new file mode 100644 index 0000000000..c9d7f5f4fb --- /dev/null +++ b/packages/hardhat-core/sample-projects/javascript-esm/scripts/deploy.js @@ -0,0 +1,22 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node