ทดลองสร้าง Non-Fungible Token (NFT) บน Ethereum Blockchain ฉบับโปรแกรมเมอร์

บทความนี้จะนำเสนอวิธีการสร้าง NFT บน Ethereum Blockchain สำหรับโปรแกรมเมอร์มือใหม่ ที่สนใจด้านการพัฒนา Smart Contract และ NFT ซึ่งถ้าคุณไม่ใช่โปรแกรมเมอร์บทความอาจจะไม่เหมาะสำหรับคุณนะครับ อีกทั้งในบทความนี้เป็นการลองทำตามบทความ How to make an NFT in 14 lines of code ของคุณ Nico ซึ่งเป็นเหมือนลักษณะการจดบันทึกเพื่อไว้ให้ผมอ่านเองในภายหลัง ดังนั้นเนื้อหาอาจไม่ได้มีอะไรแปลกใหม่ไปจากบทความข้างต้น แต่ใครทำตามแล้วไม่ได้ลองทำตามผมดูก็ได้นะครับ

Non-Fungible Token (NFT) คือ?

ทาง ethereum.org ได้ให้คำจำกัดความของ NFT เป็น Token ที่สามารถแสดงความเป็นเจ้าของของไอเท็มเฉพาะ (unique) ได้ โดย Token ในที่นี้สามารถใช้กับสิ่งต่างๆได้ เช่น งานศิลปะ ของสะสม การ์ตูน ไอเท็มในเกม หรืออสังหาริมทรัพย์ต่างๆ

ERC721 คือ?

ERC721 เป็นโปรตคอลมาตราฐานสำหรับการสร้าง Non-Fungible Token บน Ethereum network โดย ERC ย่อมาจาก Ethereum Request for Comments และ 721 คือหมายเลขของข้อเสนอ หรือ พูดง่ายๆ ERC721 คือเป็นมาตราฐานหรือข้อเสนอแนะในการสร้าง Non-Fungible Token ครับ

Mint NFT คือ?

การ Mint NFT คือ การสร้าง NFT หรือ การนำ Token ที่มีลักษณะเฉพาะขึ้นสู่ Blockchain โดยการบันทึกข้อมูลจะอยู่ในรูปแบบของ JSON ซึ่งเรียกกว่า metadata ตัวอย่างข้อมูลที่สามารถออกแบบและจัดเก็บได้ เช่น ชื่อ รูปภาพ รายละเอียด และข้อมูลอื่นๆ โดยในตัวอย่างนี้ผมจะมี metadata ดังต่อไปนี้

แล้ว metadata ของ NFT เก็บที่ไหนดี?

ปกติจะทำได้ 3 วิธี ครับ

1. เก็บบน Blockchain

2. เก็บในรูปแบบของ IPFS

3. สร้าง API ที่สามารถส่ง JSON ออกมาเลย เพื่อความสะดวกในบทความนี้จะใช้วิธีนี้นะครับ

ติดตั้ง METAMASK

ติดตั้ง METAMASK เริ่มจากติดตั้ง Metamask เป็นกระเป๋า (wallet) สำหรับบริหารจัดการ Ethereum และ Token บน Ethererum Blockchain โดยสามารถติดตั้งได้ที่ metamask.io ตามขั้นตอนซึ่งผมขออนุญาตข้ามขั้นตอนนี้ไปนะครับ

เมื่อได้ account แล้ว ขั้นตอน ต่อมาเราจะขอ ETH เข้า wallet ของเรา

ในตัวอย่างนี้ ผมจะใช้เป็น Ropsten Test Network ดังรูปต่อไปนี้

ในกรณีไม่พบ Ropsten Test Network ให้ไปที่ icon (ขวาบน) > Settings > Advanced > Show text networks เลือก on

ต่อมาขอ ETH ฟรี โดยสามารถขอได้จาก link ต่อไปนี้ โดยการใส่ wallet address ของเรา แล้วกด Send me test Ether ได้เลยครับ

เชื่อมต่อ Ethereum Network ผ่าน Alchemy

Alchemy ให้บริการในการเชื่อมต่อกับ Nthereum Network โดยมีบริการ nodes as a service ลักษณะเดียวกับ Infura Moralis และ BlockDaemon ซึ่งในบทความนี้เราจะใช้ Alchemy โดยมีขั้นตอนการสมัครดังต่อไปนี้

สมัครสมาชิก กรอกข้อมูล ได้แก่ ชื่อ นามสกุล email และรหัสผ่าน จากนั้นยืนยันการสมัครสมาชิกใน email

จากนั้นเลือก Ethereum > Get Started

กรอก team name, app name และเลือก network เป็น Ropsten > Create App

เลือก Free forever > Continue

เลือก Skip for now

Capped Capacity > Continue

ได้ยินมาจากช่องทางไหน? >Let's Go

เลือก App name ที่สร้างขึ้นมา

Copy Alchemy Key เดี๋ยวเราจะใช้ในอนาคตอันใกล้นี้ครับ

ติดตั้ง NodeJS และ NPM

เพื่อให้สะดวกในการทำงานผมแนะนำให้ติดตั้ง NVM ซึ่งเป็นตัวบริหารจัดการ Node version เนื่องจากบ่อยครั้งที่ในบางโปรเจคมีความต้องการใช้ Node version ที่แตกต่างกัน โดย NVM ทำให้สามารถเปลี่ยนแปลง version ของ Node ที่จะนำไปใช้ได้ง่ายมาก ๆ

ติดตั้ง NVM

เปิด ternimal จากนั้นสั่งคำสั่งต่อไปนี้

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

จากนั้นติดตั้ง Node version 14.16 ดังนี้

nvm install 14.17
nvm use 14.17

ทดสอบ Node version ดังนี้

สร้าง NFT

จากนั้นเริ่มสร้าง folder ชื่อ mynft-project ดังนี้

mkdir mynft-project
cd mynft-project

ต่อมาเราจะสร้าง folder ethereum อยู่ภายใน mynft-project โดยเราจะใช้ Hardhat ซึ่งเป็นเครื่องมือสำหรับพัฒนาและทดสอบการเขียนโปรแกรมบน Ethereum Blockchain

mkdir ethereum
cd ethereum

ติดตั้งและเริ่มสร้าง project ด้วย Hardhat

ติดตั้งและเริ่มสร้าง project ด้วย Hardhat ด้วยคำสั่งต่อไปนี้

npm install --save-dev hardhat
npx hardhat

จะปรากฎหน้าจอดังต่อไปนี้

โดยใช้เลือก Create an empty hardhat.config.js

กำหนดค่าต่างๆที่จำเป็น

ในตัวอย่างนี้เราจะต้องใช้ 3 อย่าง คือ

1. Alchemy key : ได้หลังจากสมัคร Alchemy

2. public key จาก Metamask : wallet address จาก Metamask ที่เราเคยใช้ตอนขอ Eth ฟรี

3. private key จาก Metemask : สามารถหาได้จากไปที่ Metamask กดที่จุด 3 จุดหลัง Account > Account details > Export Private Key > กรอก password > จากนั้นจะได้ private key มาครับ

สร้างไฟล์ .env ภายใน folder ethereum โดยติดตั้ง dotenv ดังต่อไปนี้

npm install dotenv --save
nano .env

ใส่ข้อมูลทั้ง 3 อย่างที่เตรียมไว้ลงในไฟล์ .env ดังต่อไปนี้

DEV_API_URL = 'YOUR_ALCHEMY_KEY'
PRIVATE_KEY = 'YOUR_METAMASK_PRIVATE_KEY'
PUBLIC_KEY = 'YOUR_METAMASK_ADDRESS'

สร้าง Smart Contract สำหรับ NFT

สร้าง folder contracts สำหรับเขียน Smart Contract และ scripts สำหรับ deploy และ mint NFT ภายใน folder ethereum

mkdir contracts
mkdir scripts

ติดตั้ง OpenZeppelin

การติดตั้ง OpenZeppelin เป็น open source ไลบารี่ของ Smart Contract มาตราฐานที่ผ่านการตรวจสอบแล้ว สามารถนำไปใช้งานต่อได้เลย ซึ่งสามารถติดตั้งได้ดังต่อไปนี้

npm install @openzeppelin/contracts

เขียน Smart Contract สำหรับ NFT

สร้างไฟล์ MyNFT.sol ภายใน folder contracts ดังนี้

cd contracts
nano MyNFT.sol

เพิ่ม source code ดังต่อไปนี้

ขออธิบาย code ซักหน่อยนะครับ

บรรทัด 4-5: นำเข้า module จาก OpenZeppelin โดยเราใช้ ERC721 และ Conunters

บรรทัด 11: ใน constructor ผมกำหนด ERC721 มีชื่อเป็น MyNFT และชื่อย่อเป็น mNFT

บรรทัด 13-14: override function _baseURI โดยการกำหนด YOUR_API_URL/api/erc721/ สำหรับแสดง metadata ของ NFT จาก api ที่เรากำลังจะสร้างขึ้น เช่น YOUR_API_URL/api/erc721/1 จะแสดงข้อมูลรายละเอียดของ NFT ชิ้นที่ 1 เป็นต้น

บรรทัด 17: function สำหรับ mint NFT

บรรทัด 18: โดยการ mint จะมีการกำหนดให้ _tokenIdCounter น้อยกว่า 3 มีความหมายว่า mint ได้ 3 ชิ้นครับ ซึ่งถ้าต้องการให้ได้มากกว่านั้นสามารถลบบรรทัดนี้ออกได้ครับ

บรรทัด 19: ทุกๆที่ mint จะมีเป็นการเพิ่มค่าให้ _tokenIdCounter ทีละ 1

บรรทัด 20: mint โดยใช้ _saftMint ของ OpenZeppelin

สร้าง API สำหรับ Metadata ของ NFT

ในตัวอย่างนี้จะเป็นการใช้ Next.js ในการสร้าง API ซึ่งมีรายละเอียดของ Metadata ทั้งหมดดังต่อไปนี้

cd ..
npx create-next-app@latest

ตั้งชื่อว่า web ดังนี้

จากนั้นเราจะไปที่ web/pages/api/ จากนั้นสร้าง folder ชื่อ erc721 ในนั้นเราจะสร้างไฟล์สำหรับเก็บ metadata ของ NFT โดยตั้งชื่อว่า [id].js โดยใช้คำสั่งต่อไปนี้

cd web/pages/api/
mkdir erc721
cd erc721
nano [id].js

ในไฟล์ [id].js ให้เพิ่มข้อมูลดังต่อไปนี้

ทั้งนี้ในรายละเอียดของ metadata ข้างต้น เพื่อนๆสามารถเปลี่ยนแปลงได้นะครับ เช่น image อาจจะนำ url รูปที่ต้องการใส่แทนได้นะครับ

จากนั้นไปที่ folder web แล้วสั่งคำสั่ง run Next.js ดังนี้

cd ../../../
npx run dev

ต่อมาให้ลองทดสอบเรียก api ของเราที่ web browser โดยไปที่ http://localhost:3000/api/erc721/1 จะพบว่าเราสามารถเรียก metadata ของ NFT ชิ้นที่ 1 ได้ จากนั้นลองทดสอบเปลี่ยนเลขเป็น 2 หรือ 3 ดูซึ่งจะได้ผลลัพธ์ดังนี้

ทั้งนี้จะพบว่าหน้าจอแสดงผลอาจจะไม่เหมือนกันผม เนื่องจากผมติดตั้ง plugin ชื่อว่า JSON Viwer

นอกจากนั้นหน้าจอที่รันอยู่ให้เปิดค้างไว้ก่อนนะครับ

ทำให้ api สามารถเข้าถึงจากภายนอกได้ด้วย ngrok

เนื่องจาก api ที่สร้างตอนนี้สามารถเรียกใช้งานได้เฉพาะเครื่องของเราเองเท่านั้น ดังนั้นพอให้สามารถเรียกใช้งาน api โดยผ่าน internet จากภายนอก เราจึงจำเป็นจะต้องใช้เครื่องมือเสริม คือ ngrok สำหรับสร้าง public URL และเป็น https ด้วย โดยมีขั้นตอนดังต่อไปนี้

1. ไปที่ ngrok.com จากนั้นสมัครสมาชิก และเข้าสู่หน้า dashboard

2. ติดตั้ง ngrok โดยให้ดาวน์โหลดได้ที่ https://ngrok.com/download

3. แยกไฟล์ไว้ในตำแหน่งที่ต้องการ

4. เชื่อมต่อกับ account โดยดูรายละเอียดใน dashboard โดยเปิด ternimal แล้วสั่งคำสั่งดังนี้

ngrok authtoken YOUR_AUTH_TOKEN

5. จากนั้นสั่งคำสั่งให้ api สามารถเข้าถึงได้จากภายนอก

ngrok http 3000

จากนั้นจะพบหน้าจอดังต่อไปนี้

เท่านี้ API ของเราก็สามารถเรียกได้จากภายนอกเรียบร้อยแล้วครับ โดยสามารถเข้าถึงได้จาก Forwarding URL (เส้นสีแดง) โดยเพิ่ม path เป็น https://[YOUR_NGROK_ADDRESS].ngrok.io/api/erc721/1

ดังนั้น url ดังกล่าวจะได้ผลลัพธ์ในลักษณะเดียวกันก่อนหน้านี้ครับ แต่สามารถเข้าจากภายนอกได้ เช่น ทดลองเข้าโดยใช้มือถือดูครับ

Complie และ Depoly Smart Contract สำหรับ NFT

ก่อนอื่นให้กลับไปแก้ไขไฟล์ ethereum/contracts/MyNFT.sol ในฟังก์ชั่น _baseURI ที่บรรทัด 14 ให้ return ด้วย url ได้ที่ได้ ngrok ดังนี้

return "https://[YOUR_NGROK_ADDRESS]/api/erc721/";

ติดตั้ง hardhat-ethers ด้วยคำสั่งต่อไปนี้

npm install @nomiclabs/hardhat-ethers --save-dev

แก้ไขไฟล์ hardhat.config.js ดังนี้

ต่อมาลอง complie ด้วยคำสั่งต่อไปนี้

npx hardhat compile

เมื่อ compile สำเร็จจะพบกับ folder artifacts/contracts ซึ่งจะมีไฟล์ debug และ artifact ซึ่งจะมีข้อมูลที่จำเป็นสำหรับการ deplay และ interact กับ smart contract ที่เขียนขึ้น

จากนั้นเราจะสร้างไฟล์ deploy.js ไว้ใน folder scripts ดังนี้

deploy ด้วยคำสั่งต่อไปนี้

node ./scripts/deploy.js

เมื่อ deploy สำเร็จจะพบข้อความดังนี้ MyNFT deployed: CONTRACT_ADDRESS

ซึ่งเราสามารถตรวจสอบดูว่าสามารถ deploy ไปที่ Blockchain ได้เรียบร้อยไหม โดยเข้าไปที่ https://ropsten.etherscan.io/address/CONTRACT_ADDRESS

Mint NFT

ติดตั้ง ethers.js

npm install --save ethers

เพิ่มคำสั่งใน mint.js ใน scripts โดยใส่ CONTRACT_ADDRESS ในบรรทัดที่ 14 ด้วยดังนี้

mint NFT ด้วยคำสั่งต่อไปนี้

node ./scripts/mint.js

ในกรณีที่มี 3 ชิ้น ก็ให้สั่งคำสั่ง 3 ครั้ง เนื่องจากใน Smart Contract มีคำสั่งนี้ require(_tokenIdCounter.current() < 3);

ดู NFT บน Metamask

เราสามารถดู NFT ได้ผ่านทาง Metamask บนมือถือ โดยให้ดาวน์โหลด Metamask จากนั้น login เข้า wallet

จากนั้นเลือก NFTs > Import NFTs

กรอก CONTRACT_ADDRESS > จากนั้นใส่ ID > IMPORT

ผมทดลองเพิ่ม 3 ชิ้น จะปรากฎ NFT ดังนี้

ณ จุดนี้เท่ากับว่าเราสามารถสร้าง NFT บน Test Network ของ Ethererum Blockchain ได้แล้ว เย้ๆ...ขั้นตอนเยอะหน่อยนะครับ บทความต่อๆไปจะมีเครื่องมือช่วยที่ง่ายกว่านี้รอติดตามนะครับ

บทความโดย อ.ผศ.ดร.ธรรณพ อารีพรรค

วิทยาลัยนวัตกรรมดิจิทัลเทคโนโลยี มหาวิทยาลัยรังสิต