Skip to content

Commit

Permalink
Merge pull request #1770 from nomiclabs/sample-ts-project
Browse files Browse the repository at this point in the history
Add Advanced Sample Project that uses TypeScript
  • Loading branch information
feuGeneA authored Oct 4, 2021
2 parents 24ec24e + a00345c commit 1239385
Show file tree
Hide file tree
Showing 20 changed files with 302 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-singers-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hardhat": patch
---

Add Advanced Sample Project that uses TypeScript.
5 changes: 5 additions & 0 deletions .changeset/khaki-actors-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hardhat": patch
---

Small improvements to the advanced sample project.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "advanced-typescript-project",
"version": "1.0.0",
"license": "MIT",
"dependencies": {}
}
34 changes: 34 additions & 0 deletions packages/e2e/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,39 @@ describe("e2e tests", function () {
});
}
});

describe("advanced TypeScript sample project", function () {
useFixture("advanced-ts-sample-project");

before(function () {
shell.exec(`${hardhatBinary}`, {
env: {
...process.env,
HARDHAT_CREATE_ADVANCED_TYPESCRIPT_SAMPLE_PROJECT_WITH_DEFAULTS:
"true",
},
});
});

for (const suggestedCommand of [
// This list should be kept reasonably in sync with
// hardhat-core/sample-projects/advanced-ts/README.txt
`${hardhatBinary} compile`,
`${hardhatBinary} test`,
`${hardhatBinary} run scripts/deploy.ts`,
"TS_NODE_FILES=true ts-node scripts/deploy.ts",
"REPORT_GAS=true npx hardhat test",
`${hardhatBinary} coverage`,
"npx eslint '**/*.{ts,js}'",
"npx eslint '**/*.{ts,js}' --fix",
"npx prettier '**/*.{json,sol,md}' --check",
"npx solhint 'contracts/**/*.sol'",
"npx solhint 'contracts/**/*.sol' --fix",
]) {
it(`should permit successful execution of the suggested command "${suggestedCommand}"`, async function () {
shell.exec(suggestedCommand);
});
}
});
});
});
3 changes: 3 additions & 0 deletions packages/hardhat-core/recommended-gitignore.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
node_modules
.env
coverage
coverage.json
typechain

#Hardhat files
cache
Expand Down
24 changes: 24 additions & 0 deletions packages/hardhat-core/sample-projects/advanced-ts/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
env: {
browser: false,
es2021: true,
mocha: true,
node: true,
},
plugins: ["@typescript-eslint"],
extends: [
"standard",
"plugin:prettier/recommended",
"plugin:node/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 12,
},
rules: {
"node/no-unsupported-features/es-syntax": [
"error",
{ ignores: ["modules"] },
],
},
};
46 changes: 46 additions & 0 deletions packages/hardhat-core/sample-projects/advanced-ts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Advanced Sample Hardhat Project

This project demonstrates an advanced Hardhat use case, integrating other tools commonly used alongside Hardhat in the ecosystem.

The project comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. It also comes with a variety of other tools, preconfigured to work with the project code.

Try running some of the following tasks:

```shell
npx hardhat accounts
npx hardhat compile
npx hardhat clean
npx hardhat test
npx hardhat node
npx hardhat help
REPORT_GAS=true npx hardhat test
npx hardhat coverage
npx hardhat run scripts/deploy.ts
TS_NODE_FILES=true npx ts-node scripts/deploy.ts
npx eslint '**/*.{js,ts}'
npx eslint '**/*.{js,ts}' --fix
npx prettier '**/*.{json,sol,md}' --check
npx prettier '**/*.{json,sol,md}' --write
npx solhint 'contracts/**/*.sol'
npx solhint 'contracts/**/*.sol' --fix
```

# Etherscan verification

To try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Ropsten.

In this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract:

```shell
hardhat run --network ropsten scripts/sample-script.ts
```

Then, copy the deployment address and paste it in to replace `DEPLOYED_CONTRACT_ADDRESS` in this command:

```shell
npx hardhat verify --network ropsten DEPLOYED_CONTRACT_ADDRESS "Hello, Hardhat!"
```

# Performance optimizations

For faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable `TS_NODE_TRANSPILE_ONLY` to `1` in hardhat's environment. For more details see [the documentation](https://hardhat.org/guides/typescript.html#performance-optimizations).
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as dotenv from "dotenv";

import { HardhatUserConfig, task } from "hardhat/config";
import "@nomiclabs/hardhat-etherscan";
import "@nomiclabs/hardhat-waffle";
import "@typechain/hardhat";
import "hardhat-gas-reporter";
import "solidity-coverage";

dotenv.config();

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();

for (const account of accounts) {
console.log(account.address);
}
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

const config: HardhatUserConfig = {
solidity: "0.8.4",
networks: {
ropsten: {
url: process.env.ROPSTEN_URL || "",
accounts:
process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],
},
},
gasReporter: {
enabled: process.env.REPORT_GAS !== undefined,
currency: "USD",
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
},
};

export default config;
3 changes: 3 additions & 0 deletions packages/hardhat-core/sample-projects/advanced-ts/npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hardhat.config.ts
scripts
test
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
import { ethers } from "hardhat";

async function main() {
// Hardhat always runs the compile task when running scripts with its command
// line interface.
//
// If this script is run directly using `node` you may want to call compile
// manually to make sure everything is compiled
// await hre.run('compile');

// We get the contract to deploy
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, Hardhat!");

await greeter.deployed();

console.log("Greeter deployed to:", greeter.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
19 changes: 19 additions & 0 deletions packages/hardhat-core/sample-projects/advanced-ts/test/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect } from "chai";
import { ethers } from "hardhat";

describe("Greeter", function () {
it("Should return the new greeting once it's changed", async function () {
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, world!");
await greeter.deployed();

expect(await greeter.greet()).to.equal("Hello, world!");

const setGreetingTx = await greeter.setGreeting("Hola, mundo!");

// wait until the transaction is mined
await setGreetingTx.wait();

expect(await greeter.greet()).to.equal("Hola, mundo!");
});
});
12 changes: 12 additions & 0 deletions packages/hardhat-core/sample-projects/advanced-ts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "dist",
"declaration": true
},
"include": ["./scripts", "./test", "./typechain"],
"files": ["./hardhat.config.ts"]
}
8 changes: 0 additions & 8 deletions packages/hardhat-core/sample-projects/advanced/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,5 @@ module.exports = {
files: ["hardhat.config.js"],
globals: { task: true },
},
{
files: ["scripts/**"],
rules: { "no-process-exit": "off" },
},
{
files: ["hardhat.config.js", "scripts/**", "test/**"],
rules: { "node/no-unpublished-require": "off" },
},
],
};
2 changes: 1 addition & 1 deletion packages/hardhat-core/sample-projects/advanced/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ npx solhint 'contracts/**/*.sol' --fix

To try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Ropsten.

In this project, copy the .env.template file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract:
In this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract:

```shell
hardhat run --network ropsten scripts/deploy.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
module.exports = {
solidity: "0.8.4",
networks: {
hardhat: {
initialBaseFeePerGas: 0, // workaround from https://github.com/sc-forks/solidity-coverage/issues/652#issuecomment-896330136 . Remove when that issue is closed.
},
ropsten: {
url: process.env.ROPSTEN_URL || "",
accounts:
Expand Down
3 changes: 3 additions & 0 deletions packages/hardhat-core/sample-projects/advanced/npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hardhat.config.js
scripts
test
10 changes: 4 additions & 6 deletions packages/hardhat-core/sample-projects/advanced/scripts/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ async function main() {

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
3 changes: 3 additions & 0 deletions packages/hardhat-core/src/internal/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ async function main() {
process.env.HARDHAT_CREATE_BASIC_SAMPLE_PROJECT_WITH_DEFAULTS !==
undefined ||
process.env.HARDHAT_CREATE_ADVANCED_SAMPLE_PROJECT_WITH_DEFAULTS !==
undefined ||
process.env
.HARDHAT_CREATE_ADVANCED_TYPESCRIPT_SAMPLE_PROJECT_WITH_DEFAULTS !==
undefined)
) {
await createProject();
Expand Down
Loading

0 comments on commit 1239385

Please sign in to comment.