Ethereum Smart Contracts with Next.js [Part 2] (เชื่อม Smart Contracts กับ Next.js)

Supakorn Thongtra
Dcen.io
Published in
4 min readJun 9, 2018
live coding

จากบทความ Part 1 เราได้ทำการสร้าง TodoList Smart Contracts ของเราและ deploy ลง localhost:9545 เรียบร้อยแล้ว ในบทความนี้เราก็จะมาสร้าง Next.js เพื่อเชื่อมต่อกับ Smart Contracts ของเรากัน

เริ่มสร้าง Next.js กันเลย โดยพิมพ์ command ตามนี้

mkdir todolist && cd todolist
npm init -y
npm install --save next react react-dom
mkdir pages

จากนั้นให้เพิ่ม script นี้เข้าไปใน package.json

{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}

สร้างไฟล์ index.js ไว้ใน folder pages เพิ่มโค้ด react เข้าไป แล้วทำการ save

export default () => <div>Welcome to next.js!</div>

จากนั้นลองรันโดยใช้คำสั่ง

npm run dev

แล้วไปที่ localhost:3000 จะได้เว็บหน้าตาแบบนี้

hello nextjs

ให้นำ folder ethereum-todolist ที่เราสร้างขึ้นมาจากบทความที่แล้ว ไปไว้ใน folder todolist จะได้ project structure ดังนี้

จากนั้นให้ทำการติดตั้ง web3.js

npm install web3@1.0.0-beta.34 --save

สร้างไฟล์ web3.js ไว้ใน folder ethereum-todolist แล้วเพิ่มโค้ดเข้าไปดังนี้
(เพื่อสร้าง instance ของ web3 ให้ชี้ไปที่ localhost:9545 ที่รัน Smart Contracts อยู่)

web3 instance

เมื่อเราได้ instance ของ web3 แล้ว เราจะมาสร้าง instance ของ todoList กันต่อเพื่อเอาไว้เรียกใช้ methods ต่างๆ ภายใน Smart Contracts ของเรา

สร้างไฟล์ชื่อ todolist.js ไว้ใน folder ethereum-todolist แล้วเพิ่มโค้ดเข้าไปดังนี้

ซึ่งใน method web3.eth.Contract เราต้องการ ค่า 2 ค่า ก็คือ ค่า abi ของ Smart Contracts และ ค่า Smart Contracts address ที่เราได้จากการ deploy (migrate)

เมื่อทำการสร้าง instance ที่จำเป็นต้องใช้ครบแล้ว เราจะมาเขียน UI และ methods ต่างๆ ที่ต้องใช้ในส่วนของ front-end กัน

ไปที่ไฟล์ index.js ใน folder pages แล้วสร้าง class component Index ขึ้นมา พร้อมทั้งระบุ state ที่ต้องการ ซึ่งจะมี account สำหรับระบุ public address ของผู้ใช้ที่กำลังใช้งานอยู่ (ตอนรัน truffle develop มันจะสร้างมาให้ 10 account), content สำหรับระบุ text ของ task ที่เราต้องการเพิ่มเข้าไป, tasks ใช้เก็บ tasks array ที่มีทั้งหมด

เพื่อที่จะ get ค่า account ออกมาเราต้องยิง service โดยใช้ web3 เข้ามาช่วย

ถ้าลอง console.log(accounts) ออกมาดูจะเห็นค่าดังนี้

10 accounts in truffle

เมื่อได้ accounts แล้ว เราจะเพิ่ม UI ในส่วนของการกรอก input ดังนี้

ซึ่งจะเรียกใช้ method createTask ที่เราสร้างขึ้นตอนกดปุ่ม add

ปล.จะสังเกตว่าจะใช้ method send() ในการเปลี่ยนแปลงค่าใดๆ บน Ethereum และที่ต้องระบุ gas ลงไปเพราะเปลี่ยนแปลงค่าใดๆ บน Ehtereum จะต้องเสียค่า gas เสมอ (ใน localhost ที่เราทดสอบอาจจะระบุตัวเลขตรงๆไว้เลยก็ได้ แต่ใน server Ethereum จริงๆ Metamask จะ estimate ค่า gas ที่เราควรจะจ่ายให้)

จากนั้นจะได้หน้า UI ประมาณนี้

ต่อไปเราจะทำเพิ่มในส่วนของการ get tasks ทั้งหมดออกมา
(จะใช้ getInitialProps() ซึ่งเป็น function ที่จะรันอยู่ในฝั่ง server ซึ่งเราสามารถให้มัน ยิง service แล้วโยนค่าลงมาให้กับ component ของเรา ผ่านทาง props ได้)

ตัวแปร taskIds จะเก็บ array ของ task id ทั้งหมด
จากนั้นเอา id ทั้งหมด ยิงไป getTask ทีละตัว
ทีนี้เราก็จะได้ task ที่มีอยู่ในระบบทั้งหมด
(ที่ต้องทำแบบนี้เพราะเป็นข้อจำกัดของ Solidity ที่ไม่สามารถ return array of struct ได้)

ค่าก่อน transform

ค่าที่ได้มาจะอยู่ในรูปแบบที่ไม่ค่อยสวยงาม ให้เรา map ค่าให้อยู่ในรูปแบบที่สามารถนำไปใช้งานและอ่านง่าย จะดีกว่า

หลังจากนั้นเราสามารถโยน tasks ให้กับ component Index ได้ ซึ่งสามารถเรียกใช้ได้ผ่าน this.props.tasks (ตรง return {…} คือการโยนค่า props ออกไปให้ component)

ปล.จะสังเกตว่า methods get จะใช้ call() ทั้งหมด ซึ่งหมายถึงการดึงค่าบน Ethereum เท่านั้น ไม่มีการไปเปลี่ยนแปลงค่าใดๆ และจะไม่เสียค่า gas

จากนั้นจะ setState ให้กับ tasks ที่ได้รับมาจากทาง server side ผ่าน this.props.tasks

หลังจากนั้นให้ไปสร้าง function สำหรับ toggle task ดังนี้

ทีนี้เราก็จะเอา tasks ของเราที่มีในระบบออกมาแสดงบนหน้า UI จาก code ดังนี้

ลองทดสอบ โดยพิมพ์ test แล้ว กดปุ่ม add แล้วลอง refresh browser จะเห็นว่า task ของเราเพิ่มเข้าไปในระบบแล้ว

ลองทดสอบ function toggle แล้ว refresh browser จะเห็นว่า UI มีการเปลี่ยนแปลง

ปล.ที่ต้อง refresh browser เพราะว่าตอนนี้เรายังไม่ได้ subscribe event บน Smart Contracts ของเรา

การ subscribe event จะต้องใช้ websocket เข้ามาช่วย ซึ่งในบทความหน้า (Part 3) เราจะทำการ deploy Smart Contracts ของเราขึ้นไปบน rinkeby network แล้วลองทดสอบ subscribe event บนนั้นกัน

ในบทความนี้เราก็ได้เรียนรู้เกี่ยวกับ Next.js กันไปแล้ว ซึ่งเรามีการนำ Web3.js มาใช้ในการ interact กับ Smart Contracts ของเราอีกต่อหนึ่ง มีความคาดหวังว่า ในอนาคต Web3.js อาจจะออกเวอร์ชันที่ใช้งานง่ายกว่านี้ สามารถรองรับการ return array of struct ได้ หรือ return struct ให้เราในรูปแบบของ object ที่สวยงามออกมาให้เลย ไม่ต้องทำการแปลงค่า object แบบ manual :)

--

--