Web3 Developer Journey: ethers.js

สวัสดีครับทุกคน วันนี้ผมจะมาแชร์ ประการณ์ในการทำงานเป็น Web3 Developer ของตัวผมกันหวังว่าจะเป็นแรงบันดาลใจ และแนวทางให้กับคนที่สนใจจะลองทำงานเกี่ยวกับ blockchain หรือ web3 นะครับ

สำหรับใครที่ยังไม่รู้ว่า web3 คืออะไร blockchain คืออะไรแล้วหลงเข้ามาอ่านสามารถไปอ่านกันได้ที่บทความด้านล่างนี้เลยนะครับ

โดยที่ในบทความนี้จะสอนให้ทุกคนลองเขียนโปรแกรมเพื่อทำงานร่วมกับ Ethereum Blockchain กันครับ โดยที่เจ้าตัว Ethereum เนี่ยเป็น platform ที่เป็นตัวทำให้ blockchain มีความโด่งดัง และมี community และ นักพัฒนาเป็นอันดับต้นๆของ โลก blockchain เลยทีเดียว

Ethereum นั่นทำงานโดยการเชื่อมต่อ EVM (Ethereum Virtual Machine) Node หลายๆตัวเข้าด้วยกันเป็นเครือข่าย blockchain โดยที่จะ มี smart contract ที่เป็นเหมือน โปรแกรมอัตโนมัตที่จะทำงาน ตาม code ที่ถูกเขียนขึ้นโดยที่ทุกคนสามารถเข้าไปดูได้ว่า code นั้นทำงานอย่างไร

ซึ่งเราการที่เราจะทำการติดต่อหรือทำงานร่วมกับ Ethereum ได้นั้นเราจะต้องทำงานผ่าน node แต่ละตัวของเจ้า Ethereum นั่นเองโดยที่วิธีการหลักๆในการติดต่อ กับ node นั้นเราจะใช้สิ่งที่เรียกว่า JSON RPC

JSON RPC คืออะไร

JSON RPC ก็คือ วิธีการสื่อสารประเภทหนึ่งที่ใช้ในการติดต่อสื่อสารระหว่าง application โดยจะส่งเป็น format ที่เป็น JSON นั่นเอง

{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}

แต่ว่าการติดต่อผ่าน JSON RPC นั้นก็ยังมีความยุ่งยากอยู่ระดับหนึ่งในแต่ละภาษาจึงได้สร้าง library ขึ้นมาเพื่อติดต่อกับเหล่า blockchain node ทั้งหลายขึ้นมาโดยตัวที่เราจะหยิบมาใช้ กันในบทความนี้ ก็ตามชื่อบทความเลยครับนั้นก็คือ EtherJs นั่นเองงงง โดยจะเป็นดั่งแผนภาพด้านล่าง

เริ่มต้น Coding กันเถอะ

tool แนะนำที่ใช้ลองเล่น ethers.js ก็คือออ

โดยที่อย่าลืมเปลี่ยน lib เป็น ethers.js กันนะครับ และสิ่งแรกที่เราจะเริ่มทำกันเกี่ยวกับ web3 ก็คือการสร้างตัวตน หรือว่า wallet กันครับ

Wallet คืออะไร

ในโลก blockchain นั้นเราจะสามารถ identify บุคคลใด ได้ด้วยสิ่งที่เรียกว่า key โดยที่ใครมี key นั้นจะเป็นผู้มีสิทธ์ในการทำธุรกรรม หรือว่า transaction ใดๆในระบบได้ทั้งหมด ดังนั้น ข้อควรระวังก็คือเราไม่ควรปล่อยให้ key ของเราหลุดเข้าไปใน internet โดยเฉพาะการ copy ส่งกันผ่าน chat application หรือว่า save เก็บเป็นไฟล์ใว้ใน computer เป็นอันขาด

โดยเฉพาะเหล่า developer ทั้งหลายห้าม push key ของตัวเองขึ้น github กันนะครับ

ได้ยินคำว่า key กันมาซักพักแล้ว ในทางปฏิบัติ key ที่พูดถึงก็จะหมายถึง private key นั้นเองโดยที่ wallet ของเราจะประกอบไปด้วยของ 3 ส่วน ก็คือ

  • Mnemonic Phrase
  • Private Key
  • Public Address

Mnemonic Phrase (AKA Recovery phrase, Mnemonic seed)

ถ้าคุณเคยมีประสบการณ์เกี่ยวกับการใช้ blockchain มาก่อน ไม่ว่าจะเป็น wallet ประเภทไดขั้นตนแรกสุดของการสร้าง wallet ก็คือการ random คำศัพท์ 12–24 คำขึ้นมาใช้ทำหน้าที่เป็น key ของเรานั่นเอง โดยทุกคนสามารถ อ่านคำอธิบายเต็มๆได้ ที่นี่ โดยที่ Mnemonic Phrase จะหน้าตาประมาณนี้เลย

leave coral rent someone rival next jaguar decide cup copper tail xxxxx

Private Key

หลังจากที่เราได้ Mnemonic Phrase มาในรูปแบบคำที่สามารถจดจำได้ง่ายแล้ว ทางปฏิบัติแล้วตัว Mnemonic Phrase จะถูกนำมาแปลงเป็น private key เพื่อใช้ในการ sign transaction ก่อนส่งขึ้น blockchain หน้าตาของ private key จะเป้นประมาณนี้

0xa69544348a8f689a38fdcfe85fe91486fbd4c389b33335xxxxxxxxxxxxx

Public Address

หรือว่าสิ่งที่เรียกว่า wallet address จะเป็นสิ่งที่เอาใว้ทำให้คนอื่นระบุตัวตนของเราได้ใน blockchain โดยที่ตามชื่อเลยก็คือ public เราสามารถเอาไปเผยแพร่ หรือบอกใครก็ได้เหมือนบอก เลขโทรศัพท์มือถือของเราเลยนั่นเอง

0xD8fAB0D93a428d262d222Bc0F8701aB85a0E4942

ใน code ก็จะน่าตาประมาณนี้

ผลลัพธ์ที่ได้ก็จะเห็นว่า wallet ที่ create ขึ้นมาก็จะประกอบไปด้วย 3 อย่างด้านบน

create wallet result

ถัดมาเราจะทำการ import wallet หรือ recover wallet ของเราด้วย seeds และ private key กัน

จะสั่งเกตได้ว่ากระเป๋า wallet1 ที่เราได้ import ด้วย private key จะไม่มี Mnemonic Phrase เพราะว่า private key นั้น generate มาจาก Mnemonic Phrase ตัว private key เลยไม่สามารถ recover ตัว seeds กลับมาได้นั่นเอง

Connect to the Node

ในขั้นตอนถัดมาเราก็จะทำการ connect กับ EVM node เพื่อเข้าถึงข้อมูลใน blockchain กันซึ่ง สิ่งที่เราจำเป็นต้องใช้ในการ เชื่อมต่อกับ node ก็คือ provider ซึ่ง provider นั้นจะสามารถทำให้เราใช้ wallet ที่สร้างขึ้นมา connect กับ blockchain ต่างๆได้โดยเปลี่ยนแค่ provider เท่านั้น

โดยที่เราสามารถใช้ เรียกใช้ provider ได้หลายวิธีเช่น

  • ใช้ function getDefaultProvider แล้วเลือกด้วยชื่อ network เช่น
const networkName = "mainnet" // or other network like "ropsten"
const provider = ethers.providers.getDefaultProvider(networkName)
  • เลือก connect กับ node โดยตรงโดยใช้ RPC URL “https://mainnet.infura.io/v3/"
const rpcURL = "https://mainnet.infura.io/v3/"
const provider = new ethers.providers.JsonRpcProvider(rpcURL)

สำหรับที่ต้องการหา RPC URL อื่นๆเบื้องต้นสามารถหาได้จาก ที่นี่เลยครับ มี public node rpc endpoint ให้ใช้ พอสมควรเลย

Connect Wallet to Provider

หลังจากที่เราได้สร้าง provider ขึ้นมาแล้วเราจะทำการเชื่อม wallet ของเราเข้ากับ provider เพื่อใช้งาน blockchain กัน

result

หลังจากที่ run code แล้วจะเห็นได้ว่าเราสามารถดึงข้อมูลของ chain ออกมาแสดงได้แล้ว และสำหรับใครหลายๆคน อาจจะสงสัยว่าค่าแต่ละค่ามีความหมายว่าอะไรผมจะมาอธิบายคร่าวๆให้ฟังกันครับ

EVM blockchain นั้นในความเป็นจริงใครใดๆ ก็สามารถที่จะตั้ง blockchain network ของตัวเองขึ้นมาได้ ซึ่งแต่ละ chain นั้นจะมี ข้อมูลประมาณนี้ก็คือ

  • Chain Name หรือก็คือ ชื่อของ chain ที่ทุกคนน่าจะได้ยินชื่อเหล่านี้ผ่านหูมาบ้าง เช่น Ethereum, Binance Smart Chain, Polygon, Avalanche, Fantom โดยที่แต่ละชื่อก็อาจจะสามารถถูกเรียกหรือว่าใช้ ต่างกันนิดหน่อยเช่น ETH, BSC เป็นต้น
  • Chain ID หรือ Network ID จะคล้ายๆกับ Chain name แต่ว่าจะเป็นสิ่งที่ เวลาอ้างอิงถึง จะรู้ว่าเป็น chain ไหนแน่ๆ ดังนั้นเวลา เขียน code กันเราเลยจะใช้ chain id เป็นตัวที่อ้างอิงถึง chain ใดๆ
  • Native Currency หรือที่คนทั่วไปอาจจะเรียกกันในชื่อ Ether โดยที่ในแต่ละ chain นั้นจะมีค่าเงินที่เป็นค่าเงินหลักเพียงอันเดียวเท่านั้นเช่น ETH ( Ethereum) BNB(BSC) MATIC(Polygon)

หน้าตาของ chain ใน code ก็จะเป็นประมาณนี้เลย

{
"name": "Ethereum Mainnet",
"chain": "ETH",
"network": "mainnet",
"nativeCurrency": {
"name": "Ether",
"symbol": "ETH",
"decimals": 18
},
"chainId": 1,
"networkId": 1,
}

สำหรับผู้ที่สงสัยว่า chain นั้นมีเยอะขนาดไหนสามารถเข้าไปดูได้ที่นี่เลยครับ

สำหรับ chain ที่ใครหลายๆคนน่าจะได้รู้จักกันมาบ้างแล้วเช่น

  • Ethereum Mainnet — Chain Id 1 — Currency ETH
  • Binance Smart Chain Mainnet — Chain Id 56 — Currency BNB
  • Avalanche C-Chain — Chain Id 43114 — Currency AVAX

Ropsten Testnet

สำหรับ developer ทุกคนนั้นมั่นใจว่าทุกคนก็คงไม่อยากจะเขียน program แล้วลอง run กันใน production กันตั้งแต่ตอน dev ใช้มั้ยล่ะครับซึ่งสำหรับ EVM chain นั้นก็จะมี testing network อยู่มากมายซึ่งในวันนี้เราจะมาลอง dev กันใน Ropsten Testnet กัน

โดยที่เราจะเปลี่ยน provider กัน ด้วยการเปลี่ยนจาก mainnet -> ropsten กันครับ

ถ้าทุกคนทำได้ถูกต้องจะต้องได้ chainId เป็น 3 ในตอนที่ log ออกมาดูกันนะครับ

ถัดมาเราจะไปขอรับ ether หรือว่า native currency กันเพื่อนำมาใช้ในการทำธุรกรรมต่างๆกันใน blockchain กันครับ โดยที่สามารถไปรับกันได้จาก faucet ของ Ropsten network ได้เลย ที่นี่

และเมื่อเรา run code ของเราอีกครั้งเราก็จะเห็นว่าเรามี balance เพิ่มขึ้นแล้ว

ทุกคนอาจจะสงสัยกันว่าเมื่อกี้เรากดรับมา 10 ETH นี่นาทำไมเราถึงมีตั้ง 10000000000000000000 กันนะ คำตอบก็คือใน blockchain หรือ ภาษา solidity ที่ใช้เขียน code จะไม่มี ตัวแปรประเภท ทศนิยมนั่นเองครับ เขาก็เลยใช้ตัวแปรที่เป็นจำนวนเต็มนี่ล่ะครับ แต่ว่ากำหนด decimals ขึ้นมา เพื่อบอกว่า จำนวนเต็มที่แสดงนี้มีทศนิยมอยู่กี่หลักกันแน่ ยกตัวอย่างเช่น

ETH ที่มี Decimals 18
10000000000000000000 โดยที่ 18 หลักท้ายเป็นทศนิยม
จำนวนของ ETH ที่เรามีจริงๆก็คือ 10000000000000000000 / 10 ^18 = 10 ETH

สมมุติเรามี 0.254 ETH จำนวน balance ที่จะแสดงให้เราเห้นก็คือ 0.254 * 10 ^ 18
หรือเท่ากับ 254000000000000000 นั่นเอง

ซึ่ง ethers js ก็มีตัวช่วยในการแปลงเลขเหล่านี้ให้อ่านง่ายอยู่ด้วยนั้นก็คือ function

  • formatUnits จะใช้ แปลง 10000000000000000000 -> 10.0
  • parseUnits จะใช้แปลง 10.0 -> 10000000000000000000

ตาม code ตัวอย่างด้านล่าง

Interact with Smart Contracts

งานหลักๆของ การพัฒนา Decentralize Application (Dapps) หรือ เป็น Web3 developer งานหนึ่งเลยก็คือการทำให้ application ของเรา ติดต่อกับ smart contract เพื่อดึงข้อมูลและแก้ไขข้อมูลใน blockchain ได้

Smart contract คืออะไร

สำหรับ developer แล้ว smart contract ก็คงเปรียบเหมือน code ชุดหนึ่ง หรือ class หนึ่งที่ทำงานอยู่บน blockchain เราสามารถ read ค่าบางอย่าง และ ทำการ write หรือแก้ ข้อมูลใน code ชุดนั้นได้

ตัวอย่างที่เห็นได้ชัดที่สุดและ ค่อนข้างใช้กันอย่างแพร่หลายก็คือ crypto currency หรือเหรียญ cryto ต่างๆนั่นเอง โดยที่ smart contract ของเหรียญ ที่เราจะมาใช้ใน Ropsten testnet ก็คือ
เหรียญ: FaucetToken
address: 0xFab46E002BbF0b4509813474841E0716E6730136
link:https://ropsten.etherscan.io/address/0xFab46E002BbF0b4509813474841E0716E6730136

ทำความรู้จักกันก่อนกับ Blockchain explorer

นับว่าเป็น tools ที่มีความสำคัญมากที่สุดตัวหนึ่งเลยสำหรับการใช้งาน blockchain ก็คือ blockchain explorer ซึ่งทุก blockchain จะมี web appclication ตัวนี้เอาใว้ใช้ในการ ดู Transaction, ดูเลข block, อ่าน code smart contract หรือแม้กระทั่ง interact กับ smart contract ก็ได้

Step 1: Read Smart Contract

โดยทั่วไปเราสามารถอ่านค่าจาก smart contract ได้ผ่านทาง block explorer ผ่านทางหน้า contract

จากรูปจะสังเกตเห็นได้ว่าเราสามารถ read smart contract ผ่านจากหน้าเว็บได้โดยตรงเลยเช่น name และ totalSupply ของเหรียญๆนี้

สำหรับ การอ่าน smart contract ผ่าน ethers.js สามารถเขียนเป็น code ได้ดังนี้

การที่เราจะเรียก function ต่างๆใน smart contract เราจะต้องมีสิ่งที่เรียกว่า ABI (Application binary interface) เรียกได้ว่าเป็น document หรือคู่มือในการ interact กับ smart contract ก็ได้ว่า function นี้มี parameters อะไรบ้าง type อะไรบ้าง

ซึ่งเราจะสามารถหาเจ้าตัว ABI นี้ได้จาก blockchain explorer ด้วยนั้นเอง

smart contract abi

ผลลัพท์ที่ได้ก็จะเป็นแบบนี้เลย

ซึ่งผลลัพท์ก็จะตรงกับการ read ผ่าน blockchain explorer เช่นกัน

Step 2: Write Smart Contract

ใน part ถัดมาเราจะมาลอง write contract กันดูบ้างซึ่งจะขอเกริ่นก่อนว่า ระหว่าง read กับ write เนี่ยมันต่างกันยังไง

Write (Transaction)

  • ทำให้ state และ data ของ blockchain เปลี่ยน
  • จะถูก process ด้วย miner
  • ต้องใช้ ค่า Gas (Ether)
  • Asynchronous
  • ผลลัพท์ที่ได้จะเป็น transaction hash ซึ่งต้องรอ process ต่อ ไม่การันตีว่า transaction จะ success

Read

  • เป็นการอ่านข้อมูล จาก state ของ blockchain
  • ไม่เสียค่า Gas (Ether)
  • ผลลัพท์ที่ได้จะเป็น value ของ function ที่เราเรียกเลยทันที

และในทางปฏิบัตเราจะเขียน code ต่างออกไปจากการ read ด้วย ก็คือ

  • เราจะต้อง connect ตัว wallet (Signer) เข้ากับ contract เสียก่อน
const provider =  ethers.providers.getDefaultProvider("ropsten")const wallet = new Wallet(privateKey)const connectedWallet = wallet.connect(provider)const tokenContract = new ethers.Contract("0xFab46E002BbF0b4509813474841E0716E6730136", abi,provider)const contract = tokenContract.connect(connectedWallet)

โดยที่ function ที่เราจะทำการ write จะมี 2 funtion ก็คือ

  • mint(to address, value uint256)
  • transfer(to address, value uint256)

Mint

จะเป็น function ที่เอาใว้ใช้เสกเหรียญขึ้นมาให้ walletใด wallet หนึ่ง โดยรับ parameters สองค่าคือ to (address ของ wallet ที่จะเสดเหรียญให้), value (จำนวนเหรียญที่จะเสกให้)

ผลลัพท์ที่ได้จากการ write function จะได้เป็น ข้อมูลของ transaction ที่ส่งไปที่ blockchain โดยถ้าเรานำ hash ไป search ที่ block explorer จะสามารถตาม track ได้ว่า status ของเราทำงานเสร็จรึยัง

จากภาพจะเห็นว่าที่ transaction hash ที่เราได้เมื่อกี้เสร็จเรียบร้อยแล้ว และมีการ transfer token 1 FAU ไปที่กระเป๋าของเรานั่นเอง และเมื่อเราทำการ ดูค่า balance ของ ether และ token balance จะมีการเปลี่ยนแปลงไป

https://gist.github.com/earth-np/74bb206261e6af768a9e71379b72fca8

จากภาพจะเห็นได้ว่ามี 2 อย่างที่เปลี่ยนแปลงไปนั่นก็คือ

  • Ether Balance ที่ลดลงเพราะว่าการ write smart contract นั้นจะต้องจ่ายค่า gas หรือก็คือ Ether นั่นเองจะสังเหตุได้ว่าจำนวนที่หายไปจะเท่ากับ Transaction Fee ที่แสดงอยู่ใน blockchain explorer
  • FAU Token Balance เป็นผลลัพท์ที่ได้จากการสร้างเหรียญ จำนวน 1 เหรียญมาที่กระเป๋าของเรานั่นเอง

Transfer

จะเป็น function ที่ใช้สำหรับการโอนเหรียญกันระหว่าง wallet โดยที่จะรับ parameters เหมือนกับ function mint เลยก็คือ to และ value

หลังจากที่ทำ transaction เสร็จเรียบร้อยก็จะเห็นใน blockchain explorer เราได้ทำการส่งเหรียญ จาก wallet1 (0x94fcdc9…) -> wallet2 (0x9c1b…) ได้สำเร็จแล้วนั้นเอง

Summary

ก็จบกันไปแล้วนะครับสำหรับ เส้นทางการเป็น Web3 Developer บทความแรก เรามาสรุปกันหน่อยดีกว่าว่าเราได้เรียนรู้เรื่องอะไรไปบ้างในบทความนี้

  • รู้จัก Ethereum Blockchain
  • Wallet คืออะไร ประกอบไปด้วยอะไร
  • วิธีการ เชื่อมต่อกับ Node ของ blockchain
  • รู้จัก blockchain ที่เป็น EVM อื่นๆเช่น BSC, Polygon, Ropsten Testnet
  • การอ่านข้อมูลจาก blockchain เช่น ChainId, Ether Balance
  • ethers utils ที่ช่วยในการ แปลงหน่วยไปมาระหว่าง uint256 เป็น เลขทศนิยม
  • ฺBlockchain Explorer tool ที่สำคัญมากในการพัฒนา Dapps กับ Smart Contract
  • วิธีการ Read Smart Contract (FAU Token) เช่น name, totalSupply, balanceOf
  • วิธีการ Write Smart Contract การ Mint และ Transfer token

หวังว่าบทความนี้จะเป็น แรงบันดาลใจและความรู้ให้กับคนที่สนใจในด้าน Blockchain, Web3, Defi นะครับ มีข้อสงสัยหรือว่าอยากจะแชร์หรือมี feedback เกี่ยวกับบทความ ทักมาคุยกันได้ครับ ที่นี่เลย

--

--