บทความนี้จะนำเสนอวิธีการสร้าง NFT บน Ethereum Blockchain สำหรับโปรแกรมเมอร์มือใหม่ ที่สนใจด้านการพัฒนา Smart Contract และ NFT ซึ่งถ้าคุณไม่ใช่โปรแกรมเมอร์บทความอาจจะไม่เหมาะสำหรับคุณนะครับ อีกทั้งในบทความนี้เป็นการลองทำตามบทความ How to make an NFT in 14 lines of code ของคุณ Nico ซึ่งเป็นเหมือนลักษณะการจดบันทึกเพื่อไว้ให้ผมอ่านเองในภายหลัง ดังนั้นเนื้อหาอาจไม่ได้มีอะไรแปลกใหม่ไปจากบทความข้างต้น แต่ใครทำตามแล้วไม่ได้ลองทำตามผมดูก็ได้นะครับ
ทาง ethereum.org ได้ให้คำจำกัดความของ NFT เป็น Token ที่สามารถแสดงความเป็นเจ้าของของไอเท็มเฉพาะ (unique) ได้ โดย Token ในที่นี้สามารถใช้กับสิ่งต่างๆได้ เช่น งานศิลปะ ของสะสม การ์ตูน ไอเท็มในเกม หรืออสังหาริมทรัพย์ต่างๆ
ERC721 เป็นโปรตคอลมาตราฐานสำหรับการสร้าง Non-Fungible Token บน Ethereum network โดย ERC ย่อมาจาก Ethereum Request for Comments และ 721 คือหมายเลขของข้อเสนอ หรือ พูดง่ายๆ ERC721 คือเป็นมาตราฐานหรือข้อเสนอแนะในการสร้าง Non-Fungible Token ครับ
การ Mint NFT คือ การสร้าง NFT หรือ การนำ Token ที่มีลักษณะเฉพาะขึ้นสู่ Blockchain โดยการบันทึกข้อมูลจะอยู่ในรูปแบบของ JSON ซึ่งเรียกกว่า metadata ตัวอย่างข้อมูลที่สามารถออกแบบและจัดเก็บได้ เช่น ชื่อ รูปภาพ รายละเอียด และข้อมูลอื่นๆ โดยในตัวอย่างนี้ผมจะมี metadata ดังต่อไปนี้
ปกติจะทำได้ 3 วิธี ครับ
1. เก็บบน Blockchain
2. เก็บในรูปแบบของ IPFS
3. สร้าง API ที่สามารถส่ง JSON ออกมาเลย เพื่อความสะดวกในบทความนี้จะใช้วิธีนี้นะครับ
ติดตั้ง 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 ได้เลยครับ
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 เดี๋ยวเราจะใช้ในอนาคตอันใกล้นี้ครับ
เพื่อให้สะดวกในการทำงานผมแนะนำให้ติดตั้ง 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 ดังนี้
จากนั้นเริ่มสร้าง folder ชื่อ mynft-project ดังนี้
mkdir mynft-project
cd mynft-project
ต่อมาเราจะสร้าง folder ethereum อยู่ภายใน mynft-project โดยเราจะใช้ Hardhat ซึ่งเป็นเครื่องมือสำหรับพัฒนาและทดสอบการเขียนโปรแกรมบน Ethereum Blockchain
mkdir ethereum
cd ethereum
ติดตั้งและเริ่มสร้าง 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'
สร้าง folder contracts สำหรับเขียน Smart Contract และ scripts สำหรับ deploy และ mint NFT ภายใน folder ethereum
mkdir contracts
mkdir scripts
การติดตั้ง OpenZeppelin เป็น open source ไลบารี่ของ Smart Contract มาตราฐานที่ผ่านการตรวจสอบแล้ว สามารถนำไปใช้งานต่อได้เลย ซึ่งสามารถติดตั้งได้ดังต่อไปนี้
npm install @openzeppelin/contracts
สร้างไฟล์ 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
ในตัวอย่างนี้จะเป็นการใช้ 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 ที่สร้างตอนนี้สามารถเรียกใช้งานได้เฉพาะเครื่องของเราเองเท่านั้น ดังนั้นพอให้สามารถเรียกใช้งาน 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 ดังกล่าวจะได้ผลลัพธ์ในลักษณะเดียวกันก่อนหน้านี้ครับ แต่สามารถเข้าจากภายนอกได้ เช่น ทดลองเข้าโดยใช้มือถือดูครับ
ก่อนอื่นให้กลับไปแก้ไขไฟล์ 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
ติดตั้ง 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 บนมือถือ โดยให้ดาวน์โหลด Metamask จากนั้น login เข้า wallet
จากนั้นเลือก NFTs > Import NFTs
กรอก CONTRACT_ADDRESS > จากนั้นใส่ ID > IMPORT
ผมทดลองเพิ่ม 3 ชิ้น จะปรากฎ NFT ดังนี้
ณ จุดนี้เท่ากับว่าเราสามารถสร้าง NFT บน Test Network ของ Ethererum Blockchain ได้แล้ว เย้ๆ...ขั้นตอนเยอะหน่อยนะครับ บทความต่อๆไปจะมีเครื่องมือช่วยที่ง่ายกว่านี้รอติดตามนะครับ
บทความโดย อ.ผศ.ดร.ธรรณพ อารีพรรค
วิทยาลัยนวัตกรรมดิจิทัลเทคโนโลยี มหาวิทยาลัยรังสิต