Devahoy Logo
PublishedAt

Hardhat

วิธีการสร้าง Custom Task สำหรับ Hardhat

วิธีการสร้าง Custom Task สำหรับ Hardhat

วันนี้มาลองทำ custom tasks สำหรับ Hardhat กันดีกว่า ซึ่งปกติแล้ว คำสั่งที่ผมมักใช้บ่อยๆ สำหรับ Hardhat คือ run กับ test

Terminal window
npx hardhat run <SCRIPT_FILE>
npx hardhat test

ข้อดีของ Hardhat task คือ ทำให้เราสามารถเล่นกับ Command Line ได้มากขึ้น เช่น อยากส่ง argument, options ต่างๆ เพิ่มเติม นอกเหนือจาก คำสั่งของ Hardhat ปกติ เราแค่กำหนด task และกำหนด params ให้มัน ก็ทำให้เราสามารถใช้ options ได้แล้ว

Create sample Hardhat project

ทดสอบสร้างโปรเจ็ค Hardhat ขึ้นมาแบบง่ายๆ

Terminal window
yarn init -y
yarn add hardhat -D

จากนั้น Init Project แบบ basic sample project

Terminal window
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.9.3 👷‍
✔ What do you want to do? · Create a basic sample project
✔ Hardhat project root: · /Users/chai/dev/hardhat-tasks-example
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with yarn (@nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers)? (Y/n) · y

หลังจากที่เรา Init project แล้ว จะมีไฟล์ hardhat.config.js ข้างใน มี custom task อันนึงชื่อว่า accounts

hardhat.config.js
1
task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => {
2
const accounts = await hre.ethers.getSigners()
3
4
for (const account of accounts) {
5
console.log(account.address)
6
}
7
})

Hardhat tasks

การดูว่า Hardhat มี tasks อะไรให้ใช้บ้าง ก็สามารถดูได้ด้วยคำสั่ง

Terminal window
npx hardhat

หรือ

Terminal window
npx hardhat --help

จะได้ผลลัพธ์แบบนี้

Terminal window
Hardhat version 2.9.3
Usage: hardhat [GLOBAL OPTIONS] <TASK> [TASK OPTIONS]
GLOBAL OPTIONS:
--config A Hardhat config file.
--emoji Use emoji in messages.
--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.
--tsconfig A TypeScript config file.
--verbose Enables Hardhat verbose logging
--version Shows hardhat's version.
AVAILABLE TASKS:
accounts Prints 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
flatten Flattens and prints contracts and their dependencies
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
To get help for a specific task run: npx hardhat help [task]

ซึ่งถ้าเราสังเกตตรง AVAILABLE TASKS จะเห็น

Terminal window
accounts Prints the list of accounts

เหมือนกับ task ที่กำหนดไว้ใน hardhat.config.js เลย

Create new task

ลองเพิ่ม Task ง่ายๆ แบบง่ายสุดคือ task ชื่อ ahoy เพื่อทำการแสดง Hello World ที่ไฟล์ hardhat.config.js

hardhat.config.js
1
task('ahoy', 'Prints Hello World', async (taskArgs, hre) => {
2
console.log('Hello World!')
3
})

เมื่อรัน npx hardhat จะเห็นว่ามี Available Task เพิ่มมาแล้ว

Terminal window
AVAILABLE TASKS:
accounts Prints the list of accounts
ahoy Prints Hello World

ลองรันคำสั่งดู

Terminal window
npx hardhat ahoy

ได้ผลลัพธ์ :

Terminal window
Hello World!

Balance Task

ลองสร้าง Task สำหรับ check balance ดูบ้าง (เวลาที่ต้องการดูว่า task นั้นๆ ใช้คำสั่งอะไรมี option อะไรบ้าง ใช้ npx hardhat help <TASK>)

hardhat.config.js
1
task('balance', "Prints an account's balance")
2
.addParam('account', "The account's address")
3
.setAction(async (taskArgs) => {
4
const account = taskArgs.account
5
const balance = await hre.ethers.provider.getBalance(account)
6
console.log(`Account balance : ${balance}`)
7
})
  • addParams() - คือกำหนด option ให้กับ task ครับ พร้อมคำอธิบาย
  • setAction() - เป็นการกำหนด action ให้กับ task โดยใช้ taskArgs ก็คือค่าที่ส่ง option จาก command line
  • hre - เป็น Hardhat runtime environment เป็น global variable ถ้าเราใช้คำสั่ง npx hardhat
  • hre.ethers เป็นตัว hardhat-ethers ที wrap ethers.js และมี helper functions เพิ่มมานิดหน่อย

ทดสอบรัน script :

Terminal window
npx hardhat balance --account 0x90F79bf6EB2c4f870365E785982E1f101E93b906

ตัว option เราสามารถทำเป็น optional ได้ เช่น task เดิม แต่เปลี่ยน ถ้าไม่ส่ง --account จะใช้ default

hardhat.config.js
1
task('balance', "Prints an account's balance")
2
.addOptionalParam('account', "The account's address")
3
.setAction(async (taskArgs) => {
4
const account = taskArgs.account || (await hre.ethers.getSigner()).address
5
const balance = await hre.ethers.provider.getBalance(account)
6
console.log(`Account balance : ${balance}`)
7
})

Create tasks folder

นอกจากเราสร้าง task ใน hardhat.config.js เรายังสามารถสร้าง task ไว้ที่ไหนก็ได้ แล้วก็ import มาใช้ เช่น ตัวอย่าง สร้าง task ที่โฟลเดอร์ tasks ชื่อว่า block-number.js

tasks/block-number.js
1
task('block-number', 'Prints the current block number', async (taskArgs, hre) => {
2
await hre.ethers.provider.getBlockNumber().then((blockNumber) => {
3
console.log(`Block number : ${blockNumber}`)
4
})
5
})

ทีนี้ใน hardhat.config.js เราก็แค่ import ไฟล์นี้มาใช้

1
require('./tasks/block-number')

แค่นี้เราก็ใช้ task ที่เราสร้างขึ้นมาได้แล้ว

Terminal window
npx hardhat block-number

สรุป

บทความนี้ก็เป็นตัวอย่างการใช้ Hardhat task เบื้องต้นด้วย JavaScript คิดว่าหลายๆ คนน่าจะพอเห็นภาพ และนำไปประยุกต์ใช้ได้หลากหลายครับ เช่น สร้าง task เอาไว้ ลอง test transfer ลอง approve ลอง logic เล็กๆ น้อยๆ รวมถึงลองใช้เป็นแบบ TypeScript จะเข้าใจง่ายกว่า เพราะจะรู้ว่าแต่ละ options, tasks, actions รับค่าอะไรบ้าง

ซึ่งจริงๆ ตัว task ของ hardhat ก็ยังทำอะไรได้มากกว่านี้ ตัวอย่างบทความ ที่น่าสนใจ อ่านเพิ่มเติมครับ Building your own Custom Hardhat Plugins from scratch

Happy Coding ❤️

Reference

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust