วิธีการดึงข้อมูลภายนอกจาก web API มาใช้ใน Smart Contract ด้วย Provable Oracle

ปกติแล้ว Smart Contract จะไม่สามารถเรียกข้อมูลจากภายนอก Blockchain มาใช้งานได้โดยตรง ตัวอย่างข้อมูลเช่น ราคาน้ำมัน ราคาหุ้น ราคา Bitcoin หรือราคาทอง เป็นต้น รวมถึงอาจมีความจำเป็นต้องประมวลข้อมูลอะไรบางอย่างภายนอก่อนจากนั้นจึงส่งผลลัพธ์กลับเข้าไปใน Smart Contract อีกที ดังนั้นวันนี้ผมแนะนำวิธีการดึงข้อมูลภายนอกจาก web API มาใช้ใน Smart Contract ด้วย Provable Oracle

Oracle คือ?

Oracle เป็นบริการที่ใช้ Smart Contract เชื่อมกับข้อมูลภายนอกเครือข่ายเพื่อเป็นตัวกลางที่คอยป้อนข้อมูลเข้าสู่ Smart Contract หรือเครือข่ายภายใน Blockchain ซึ่งในตัวอย่างนี้ผมจะลองใช้ Provable oracle smart contract (Provable เมื่อก่อนใช้ชื่อว่า Oraclize)

Provable ตอนนี้สามารถเรียกใช้งานได้ครั้งแรกฟรี แต่ครั้งต่อไปจะมีค่าใช้จ่ายดังนี้ครับ link

API ที่ใช้ในบทความนี้

ในบทคววามนี้ผมจะใช้ api จากที่แสดงราคา Bitcoin และ Ethereum ซึ่งทั้ง 2 จะอยู่ในรูปแบบของ JSON โดยมี URL และ respone (ซึ่งค่าที่เราต้องการอยู่ใน key price) ดังต่อไปนี้

Bitcoin URL: https://api.pro.coinbase.com/products/BTC-USD/ticker

{
"ask": "16750.5",
"bid": "16749.44",
"volume": "12921.51869227",
"trade_id": 472611614,
"price": "16750.5",
"size": "0.00298126",
"time": "2022-12-19T11:17:17.925158Z"
}

Ethereum URL: https://api.pro.coinbase.com/products/BTC-USD/ticker

{
"ask": "1184.86",
"bid": "1184.85",
"volume": "190725.861376",
"trade_id": 401079821,
"price": "1184.86",
"size": "0.2832",
"time": "2022-12-19T11:25:45.301160Z"
}

https://api.pro.coinbase.com/products/BTC-USD/ticker จากนั้นติดตั้งตามขั้นตอน

ติดตั้ง METAMASK

ผมจะใช้ Metamask เป็นกระเป๋าดิจิทัล (digital wallet) สำหรับบริหารจัดการ Ethereum ซึ่งสามารถติดตั้งได้ที่ metamask.io จากนั้นติดตั้งตามขั้นตอน

เปิด Sepolia test network

หลังจากติดตั้ง Metamask และได้ account เรียบร้อยแล้ว ต่อมาจะเป็นเปิด Sepolia testnet ซึ่งเป็น network ไว้สำหรับทดสอบทำให้ไม่ต้องจ่ายค่าธรรมเนียมด้วย ETH จริงๆ

ให้ไปที่ Ethereum Mainnet ด้านบน > เลือก Show/hide > Show test networks เลือก ON > จากนั้นเลือก Network ไปที่ Sepolia testnet ตัวอย่างดังรูป

ซึ่งตอนนี้จะพบว่าเรามี 0 SepoliaETH ดังนั้นขั้นตอนต่อไปเราจะไปขอ ETH กัน

ขอ ETH ฟรี

ปัจจุบันมีหลายช่องทางแต่ผมขอแนะนำของ Laika ดังนี้ครับ

web.getlaika.app/faucets (0.1 ETH ต่อครั้ง) > เลือก Request Faucet ดังรูป

จากนั้น กรอก Address > ทำเครื่องหมายถูก I am human ยืนยัน captcha ให้ผ่าน > Send Request ดังรูป

รอซักพักจะพบว่าได้รับ 0.1 ETH

เขียน smart contract

ผมใช้เครื่องมือในการเขียน คือ Remix ซึ่งเป็น IDE ที่สามารถเขียน compile และ deploy โดยภาษา Solidity กัน

โดยให้เข้าไปที่ remix.ethereum.org > เลือก Solidity > เลือก New file > ตั้งชื่อไฟล์ OracleContract.sol

จากนั้นเพิ่มโค้ด ทั้งนี้ผมขออธิบายรายละเอียดแทรกไว้เป็น Comment ภายในโค้ดเลย ดังนี้

Compile โค้ด

จากนั้น compile โดยไปที่หน้า SOLIDITY COMPILE > เลือก 0.8.17+commit > กด Compile OracleContract.sol ดังรูป

Deploy ไปที่ Sepolia testnet

จากนั้น Deploy ไปที่ Sepolia testnet โดยไปที่หน้า DEPLOY & RUN TRANSACTIONS > เลือก Injected Provider - Metamask > เลือก Deploy

กด Confirm ค่าธรรมเนียมในการ Deploy โค้ด ซึ่งจ่ายเป็น XTH ดังนี้

ทดลองดึงข้อมูลภายนอกจาก WEB API

หลังจาก Deploy เรียบร้อยแล้ว จะพบ Deployed Contracts (อยู่ซ้ายล่างของจอ) ซึ่งเราจะได้ Contract Address และพบฟังก์ชั่นต่างๆที่เราสามารถเรียกใช้งานได้ ดังนี้

จากนั้น เราจะลองทดลองดึงข้อมูลราคาของ Bitcoin จากด้วยฟังก์ชั่น getPrice โดยใส่ symbol เป็น BTC จากนั้กดที่ getPrice > Confirm ค่า ​Gas ดังนี้

เราสามารถดูผลลัพธ์การทำงานต่างๆได้ที่ https://sepolia.etherscan.io/ จากนั้นให้นำเลข Contract Address ไปค้นที่ช่องค้นหาดังนี้

จากนั้นจะพบรายละเอียด transaction ทั้งหมดที่เกิดขึ้นของ Contract นี้ ดังนี้

โดยจากรูปข้างต้นจะพบว่ามีทั้งหมด 3 transcation ได้แก่

1. Oxdc193 คือ transaction ของการ deploy smart contract

2. Ox0f337 คือ transaction ของ getPrice เพื่อไป query ราคาจาก web API

3. Oxdacdb คือ transaction ที่เกิดขึ้นตอนได้ผลลัพธ์กลับมาแล้วมีการบันทึกผลลัพธ์ไว้

ทั้งนี้เราสามารถดู event ที่เกิดขึ้นได้ โดยการไปที่ Events ดังนี้

จะพบว่า event แรกแสดงข้อความว่า Query called ซึ่งถูกเรียกใน transaction Ox0f337 ตอนที่ไป query ราคาจาก web API

และ event ที่สองแสดงค่า 16785.92 คือ ผลลัพธ์จากการ query ราคา Bitcoin ซึ่งถูกเรียกใน function callback เพื่อบันทึกค่าในตัวแปร ดัง transaction Oxdc193

จากนั้นลองทดสอบเรียกค่าจากตัวแปร btc_usd โดยกดที่ btc_usd ได้ค่าราคา Bitcoin คือ 16785.92 ดังรูป

ในกรณีไม่แสดงค่า ให้รอซักพัก เพราะ 2 transaction ข้างต้นอาจจะยังไม่เสร็จ

จากนั้นลองทดลองดึงราคา Ethereum บ้าง ด้วยฟังก์ชั่น getPrice โดยใส่ symbol เป็น ETH จากนั้กดที่ getPrice > Confirm ค่า ​Gas ดังนี้

รอซักครู่ จะพบว่าดึงราคาไม่ได้ให้ลองไปดูที่ Events ใน explorer จะพบว่าข้อความว่า Not sufficient funds ดังนี้

เนื่องจาก Provable จะเรียกใช้งานได้ฟรีเฉพาะครั้งแรกเท่านั้น ครั้งต่อๆไปจะต้องเสียค่าธรรมเนียม

ดังนั้นเราจะโอน ETH ใส่ไว้ใน contract โดยใช้ไปที่ Metamask > Send > กรอก contract address > ใส่ ETH ไว้ซัก 0.01 > Next > Confirm

รอซักครู่จะพบว่า ETH โอนเข้าใน contract เรียบร้อยแล้ว ดังนี้

จากนั้นให้ทดลอง getPrice โดยใส่ symbol เป็น ETH อีกครั้ง จากนั้นลองเรียก eth_usd จะได้ผลลัพธ์ดังต่อไปนี้

สังเกตว่า ETH ใน contract จะถูกดึงออกไปสำหรับจ่ายค่าธรรมเนียมครับ

เท่านี้เราก็สามารถดึงข้อมูลจากภายนอกจาก web API มาใช้ภายใน contract ได้เรียบร้อยแล้วครับ

หวังว่าบทความนี้คงเป็นประโยชน์ไม่มากก็น้อยนะครับ ลองนำไปต่อยอดกันดูนะครับ มีเวลาจะมาแบ่งปันอีกเรื่อยๆครับ

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

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