วิธีการสร้าง Custom Task สำหรับ Hardhat
วันนี้มาลองทำ custom tasks สำหรับ Hardhat กันดีกว่า ซึ่งปกติแล้ว คำสั่งที่ผมมักใช้บ่อยๆ สำหรับ Hardhat คือ run
กับ test
npx hardhat run <SCRIPT_FILE>
npx hardhat test
ข้อดีของ Hardhat task คือ ทำให้เราสามารถเล่นกับ Command Line ได้มากขึ้น เช่น อยากส่ง argument, options ต่างๆ เพิ่มเติม นอกเหนือจาก คำสั่งของ Hardhat ปกติ เราแค่กำหนด task และกำหนด params ให้มัน ก็ทำให้เราสามารถใช้ options ได้แล้ว
Create sample Hardhat project
ทดสอบสร้างโปรเจ็ค Hardhat ขึ้นมาแบบง่ายๆ
yarn init -y
yarn add hardhat -D
จากนั้น Init Project แบบ basic sample project
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
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);
}
});
Hardhat tasks
การดูว่า Hardhat มี tasks อะไรให้ใช้บ้าง ก็สามารถดูได้ด้วยคำสั่ง
npx hardhat
หรือ
npx hardhat --help
จะได้ผลลัพธ์แบบนี้
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 จะเห็น
accounts Prints the list of accounts
เหมือนกับ task ที่กำหนดไว้ใน hardhat.config.js
เลย
Create new task
ลองเพิ่ม Task ง่ายๆ แบบง่ายสุดคือ task ชื่อ ahoy เพื่อทำการแสดง Hello World ที่ไฟล์ hardhat.config.js
task("ahoy", "Prints Hello World", async (taskArgs, hre) => {
console.log("Hello World!");
});
เมื่อรัน npx hardhat
จะเห็นว่ามี Available Task เพิ่มมาแล้ว
AVAILABLE TASKS:
accounts Prints the list of accounts
ahoy Prints Hello World
ลองรันคำสั่งดู
npx hardhat ahoy
ได้ผลลัพธ์ :
Hello World!
Balance Task
ลองสร้าง Task สำหรับ check balance ดูบ้าง (เวลาที่ต้องการดูว่า task นั้นๆ ใช้คำสั่งอะไรมี option อะไรบ้าง ใช้ npx hardhat help <TASK>
)
task("balance", "Prints an account's balance")
.addParam("account", "The account's address")
.setAction(async (taskArgs) => {
const account = taskArgs.account;
const balance = await hre.ethers.provider.getBalance(account);
console.log(`Account balance : ${balance}`);
});
addParams()
- คือกำหนด option ให้กับ task ครับ พร้อมคำอธิบายsetAction()
- เป็นการกำหนด action ให้กับ task โดยใช้taskArgs
ก็คือค่าที่ส่ง option จาก command linehre
- เป็น Hardhat runtime environment เป็น global variable ถ้าเราใช้คำสั่งnpx hardhat
hre.ethers
เป็นตัว hardhat-ethers ที wrap ethers.js และมี helper functions เพิ่มมานิดหน่อย
ทดสอบรัน script :
npx hardhat balance --account 0x90F79bf6EB2c4f870365E785982E1f101E93b906
ตัว option
เราสามารถทำเป็น optional ได้ เช่น task เดิม แต่เปลี่ยน ถ้าไม่ส่ง --account
จะใช้ default
task("balance", "Prints an account's balance")
.addOptionalParam("account", "The account's address")
.setAction(async (taskArgs) => {
const account = taskArgs.account || (await hre.ethers.getSigner()).address;
const balance = await hre.ethers.provider.getBalance(account);
console.log(`Account balance : ${balance}`);
});
Create tasks folder
นอกจากเราสร้าง task ใน hardhat.config.js
เรายังสามารถสร้าง task ไว้ที่ไหนก็ได้ แล้วก็ import มาใช้ เช่น ตัวอย่าง สร้าง task ที่โฟลเดอร์ tasks ชื่อว่า block-number.js
task(
'block-number',
'Prints the current block number',
async (taskArgs, hre) => {
await hre.ethers.provider.getBlockNumber().then((blockNumber) => {
console.log(`Block number : ${blockNumber}`);
});
}
);
ทีนี้ใน hardhat.config.js
เราก็แค่ import ไฟล์นี้มาใช้
require('./tasks/block-number');
แค่นี้เราก็ใช้ task ที่เราสร้างขึ้นมาได้แล้ว
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
- Name
- Chai Phonbopit
- Website
- @Phonbopit