TypeScript + Hardhatで始めるスマートコントラクト開発環境構築

# はじめに
こんにちは。株式会社HRBrainで23卒内定者インターンをしている [RAO](https://twitter.com/mth_rao)です。
この記事は、HRBrain Advent Calendar 2022 14日目の記事です。

https://qiita.com/advent-calendar/2022/hrbrain

「HR系の会社なのにスマートコントラクト開発！？」なんて思った方いませんか？
そうです。その通りです。迷いに迷って大学の研究に関連する内容にしました。
なので、業務内容とは何も関係無いので悪しからず。

# 前提
本章はスマートコントラクト開発における前提知識のお話なので、読み飛ばして頂いても構いません。

## スマートコントラクトって何？
ブロックチェーン上で契約を自動化する仕組みのことを言います。この仕組みはよく自動販売機に例えられます。
ユーザーが自動販売機にお金を入れ、商品のボタンを押下した瞬間に購入の契約が成立するイメージです。
上記のような契約をプログラミング言語で記述し、自動化したものをスマートコントラクトと言います。

ちなみにコン**ス**トラクトとよく間違いが起きるので注意です。


## Hardhatって何？
>Hardhat is a development environment for Ethereum software. It consists of different components for editing, compiling, debugging and deploying your smart contracts and dApps, all of which work together to create a complete development environment.

出典：https://hardhat.org/hardhat-runner/docs/getting-started

日本語訳すると
>HardhatはEthereumソフトウェア用の開発環境です。スマートコントラクトやdAppを編集、コンパイル、デバッグ、デプロイするためのさまざまなコンポーネントで構成されており、これらすべてが連動して完全な開発環境を作り上げます。

Ethereum というプラットフォームを用いると分散アプリケーション（DApps）開発が容易になりますが、そのためにスマートコントラクト開発なら[Truffle](https://trufflesuite.com/docs/truffle/)、ノードやネットワーク開発なら[Ganache](https://trufflesuite.com/docs/ganache/)のようなEthereum用フレームワークの併用が一般的でした。
しかしHardhatを使えば、それだけで開発したスマートコントラクトのコンパイル・テスト・デプロイなどが行えるので便利です。
今までGanacheやTruffleを併用してきた方にとっては、オールインワンで開発可能になるので、大きな開発体験の向上を感じる事ができると思います。


# 本題
## プロジェクトの設定
|モジュール名|バージョン|
|-|-|
|Hardhat|2.12.3|
|yarn|1.22.19|

Hardhatの公式チュートリアルを参考に進めていきましょう。
まずディレクトリを作成します。ディレクトリ名は何でも大丈夫です。
```zsh
$ mkdir hardhat-tutorial
$ cd hardhat-tutorial
```

package.jsonを生成して、hardhatをインストールします。
```zsh
$ yarn init
$ yarn add --dev hardhat
```

`npx hardhat`とするとscaffoldが出てくるので`Create a TypeScript project`を選択します。
```zsh
$ npx hardhat
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.12.3 👷‍

? What do you want to do? … 
  Create a JavaScript project
❯ Create a TypeScript project
  Create an empty hardhat.config.js
  Quit
```

便利なプラグイン等をインストールします（ここはよしなに変更して大丈夫です）。
```zsh
yarn add --dev @nomicfoundation/hardhat-toolbox @nomicfoundation/hardhat-network-helpers @nomicfoundation/hardhat-chai-matchers @nomiclabs/hardhat-ethers @nomiclabs/hardhat-etherscan chai ethers hardhat-gas-reporter solidity-coverage @typechain/hardhat typechain @typechain/ethers-v5 @ethersproject/abi @ethersproject/providers
```

ここで`npx hardhart`としてみます。現在利用可能なタスク一覧を取得できます。
```zsh
$ npx hardhat
Hardhat version 2.12.3

Usage: hardhat [GLOBAL OPTIONS] <TASK> [TASK OPTIONS]

GLOBAL OPTIONS:

  --config              A Hardhat config file. 
  --emoji               Use emoji in messages. 
  --flamegraph          Generate a flamegraph of your Hardhat tasks 
  --help                Shows this message, or a task's help if its name is provided 
  --max-memory          The maximum amount of memory that Hardhat can use. 
  --network             The network to connect to. 
  --show-stack-traces   Show stack traces (always enabled on CI servers). 
  --tsconfig            A TypeScript config file. 
  --typecheck           Enable TypeScript type-checking of your scripts/tests 
  --verbose             Enables Hardhat verbose logging 
  --version             Shows hardhat's version. 


AVAILABLE TASKS:

  check                 Check whatever you need
  clean                 Clears the cache and deletes all artifacts
  compile               Compiles the entire project, building all artifacts
  console               Opens a hardhat console
  coverage              Generates a code coverage report for tests
  flatten               Flattens and prints contracts and their dependencies
  gas-reporter:merge
  help                  Prints this message
  node                  Starts a JSON-RPC server on top of Hardhat Network
  run                   Runs a user-defined script after compiling the project
  test                  Runs mocha tests
  typechain             Generate Typechain typings for compiled contracts
  verify                Verifies contract on Etherscan

To get help for a specific task run: npx hardhat help [task]
```
JavaScriptのサンプル作成時ではデフォルトで`accounts`がありましたが、無さそうなので追加してみます。
タスクはhardhat.config.tsに定義します。
```ts
import { HardhatUserConfig, task } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import { HardhatRuntimeEnvironment } from "hardhat/types";

const accounts = async (args: string, hre: HardhatRuntimeEnvironment) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
};
task("accounts", "Show the list of accounts", accounts);

const config: HardhatUserConfig = {
  solidity: "0.8.17",
};

export default config;
```
もう一度、`npx hardhat`とすると`accounts`が追加出来ている事を確認できます。
```zsh
$ npx hardhat
~~~~
省略
~~~~
AVAILABLE TASKS:

  accounts              Show the list of accounts
  check                 Check whatever you need
  clean                 Clears the cache and deletes all artifacts
  compile               Compiles the entire project, building all artifacts
  console               Opens a hardhat console
  coverage              Generates a code coverage report for tests
  flatten               Flattens and prints contracts and their dependencies
  gas-reporter:merge
  help                  Prints this message
  node                  Starts a JSON-RPC server on top of Hardhat Network
  run                   Runs a user-defined script after compiling the project
  test                  Runs mocha tests
  typechain             Generate Typechain typings for compiled contracts
  verify                Verifies contract on Etherscan
~~~~
省略
~~~~
```
タスクは`npx hardhat [タスク名]`で実行できます。
アドレスはマスクしています。
```zsh
$ npx hardhat accounts
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864822/268ccd27-0fb5-8437-c187-bd8753f70a69.png)

TypeScriptをインストールしましょう。
```zsh
yarn add --dev ts-node typescript
```
型情報もインストールしましょう。
```zsh
yarn add --dev @types/node @types/mocha @types/chai
```

`tsconfig.json`はこんな感じです。
```json
{
  "compilerOptions": {
    "target": "es2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
```
# 追伸
はじめにでも記載しましたが、自分は23卒内定者としてHRBrainでインターンをしています。
インターンとして、新規プロダクトの開発をメインでゴリゴリやらせて頂いています！
スタートアップでインターンしてみたい！っていう学生是非お待ちしています。

HRBrainはCore Value（Intensity、 Take Ownership、 Power to the team）に共感する方を募集しています！

https://www.hrbrain.co.jp/recruit

最後までご覧いただきありがとうございました。