Web3.js 101

pasupol bunsaen
Sep 8, 2018 · 6 min read

ก่อนอื่นเลย ถ้าผิดตรงส่วนไหน ต้องขออภัย และโปรดแจ้งด้วยครับ -/\-

อธิบายสั้นๆ

Web3.js เป็น JavaScript Library ที่ใช้ติดต่อกับโหนดของ Ethereum ผ่านทาง Http หรือ IPC

การติดตั้ง

npm install web3

หลังจากติดตั้งเสร็จแล้ว ให้สร้างไฟล์ app.js ขึ้นมาแล้วพิมพ์โค้ดตามนี้ครับ

const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("Web3 Provider"));

ในบรรทัดที่ 1 : เป็นการเรียก web3 ที่เราได้ทำการติดตั้งในก่อนหน้านี้ มาใช้งาน

ในบรรทัดที่ 2 : ทำการสร้าง Object ขึ้นมาใหม่ และกำหนด Provider ให้กับ web3

Web3 Provider

ก่อนจะพูดถึง Web3 Provider ต้องเล่าก่อนว่า Ethereum Blockchain เกิดจากโหนด หลายๆโหนด ที่มีการแชร์ข้อมูลระหว่างกัน โดยมีข้อมูลเป็นชุดเดียวกัน ทั้งหมด

และการตั้งค่า Web3 Provider ใน web3.js ก็เป็นการประกาศว่า เราจะทำการเชื่อม ไปยังโหนดไหน บน Ethereum เพื่ออ่าน หรือ เขียน ข้อมูล บนโหนดนั้น ซึ่งเราสามารถ ตั้งโหนด ขึ้นมาเองได้ โดยใช้ geth (Go-Ethereum | Command line Interface) หรือ จะใช้ของ Third-Party ต่างๆที่เปิดให้ใช้งานก็ได้ เช่น Infura เป็นต้น

คำสั่งพื้นฐาน

สร้าง Account

web3.eth.accounts.create());{ address: '0xcf4ca355ec55724dec46404b360bc00e516f6e8f',
privateKey: '0x9a628051acf4e3ada996d5be2f5b9918ccba57bc7e6affdb6899eed1b9e8c657',
signTransaction: [Function: signTransaction],
sign: [Function: sign],
encrypt: [Function: encrypt]
}

จากคำสั่งด้านบน จะ Generate Account ออกมาได้ทีละอัน ถ้าอยากสร้างทีละหลายๆ Account ให้ใช้คำสั่ง wallet.create();

const wallet = web3.eth.accounts.wallet.create(2);console.log(wallet);Wallet {
0: {...},
"0xF0109fC8DF283027b6285cc889F5aA624EaC1F55": {...},
"0xf0109fc8df283027b6285cc889f5aa624eac1f55": {...},
...
}

ตรวจสอบ ยอดคงเหลือ

web3.eth.getBalance(“0xcf4ca355ec55724dec46404b360bc00e516f6e8f”, function(error, balance) {
if(!error) {
console.log(web3.utils.fromWei(balance, 'ether'));
}
});

ตรวจสอบ Block ที่กำลังสร้างขึ้นมาใหม่

web3.eth.getBlock(“pending”).then(function(result) {
console.log(result);
})

ตรวจสอบ เลขของ Block ล่าสุด

web3.eth.getBlockNumber().then(function(result) {
console.log(result)
})
//3998546

ถ้าตามไปเช็คที่ Etherscan.io จะเห็นตามนี้

แสดงรายละเอียดต่างๆใน Block

web3.eth.getBlock(“3998546”).then(function(result) {
console.log(result)
})
{ difficulty: '6707125341',
extraData: '0x706c732073657420686967686572207461726765746761736c696d6974',
gasLimit: 7987834,
gasUsed: 29334,
hash: '0xd1dd5710815711d627dc146999522c93792960565ad79f06171ecbe3b0818964'
...
...
...
}
ถ้าเป็น block ล่าสุด สามารถใช้คำสั่ง web3.eth.getBlock("latest") แทนได้

ลองเขียนโค้ด ดึงข้อมูล ย้อนหลัง 10 Block

web3.eth.getBlockNumber().then(function(result) {
for(let i = 1; i< 10; i++) {
web3.eth.getBlock(result -1).then(function(block) {
console.log(block);
});
}
});

แสดงข้อมูลของ Block ล่าสุดแบบ Real Time โดยใช้ Websocket

const Web3 = require(‘web3’);
const ws = “wss://ropsten.infura.io/ws”;
const web3 = new Web3(ws);
web3.eth.subscribe(“newBlockHeaders”, function(error, block) {
if(!error) {
console.log(block);
}
}
);
gif

Subscribe Event แบบระบุ Wallet

ใช้ตรวจสอบ เมื่อมีการโอน Ether มาที่ wallet ที่เรากำหนด เช่นนำไปใช้ยืนยันการโอนเข้า เพื่อซื้อสินค้าเป็นต้น

เมื่อฝั่งลูกค้าทำการโอน (ทดสอบบน Metamask)

ผลลัพธ์

from: 0xcF4CA355eC55724DEC46404B360bC00E516f6E8F amount: 0.1

อธิบายโค้ด

บรรทัดที่ 1 : ทำการ Subscribe pendingTransactions ทั้งหมดที่เกิดขึ้นบน Ethereum Network ผ่านทาง Websocket บนโหนดของ Infura ในตัวอย่างนี้ทดสอบบน Ropsten Network

เมื่อมี Transaction ใหม่เกิดขึ้นจะ Return ออกมาเป็น Hash

บรรทัดที่ 4 : นำ Hash ที่ได้ มาเข้า Function getTransaction เพื่อหารายละเอียดทั้งหมด

บรรทัดที่ 6 : ตรวจสอบ ปลายทางของ Wallet ที่โอนถึง ว่าตรงกับ Wallet ที่เราตั้งไว้หรือไม่ ถ้าใช่ ก็แสดง Wallet ของต้นทาง กับ จำนวน Ether ที่โอนมา

การโอน (Signing transactions)

ในการโอน Ether (แบบไม่ใช้ Metamask) ส่วนใหญ่จะใช้ Library อีกตัวนึง ที่ชื่อว่า ethereumjs-tx ซึ่งช่วยในการจัดการ ในเรื่องของการ สร้าง Transaction โดยตรง

การติดตั้ง

npm install ethereumjs-tx

โค้ดทั้งหมด

อธิบายโค้ด

บรรทัดที่ 1,2,3 : เป็นการเรียก Library เข้ามาใช้งาน

บรรทัดที่ 4 : กำหนด Provider ให้กับ Web3 ในที่นี้เลือกเป็น Ropsten Network

บรรทัดที่ 6 : เปลี่ยน รูปแบบของ Private Key ให้อยู่ในรูปแบบของ Hex แบบจับคู่
ซึ่งแต่เดิม Private Key จะเป็นการ Random String มา 256 bit โดยใช้ อัลกอริทึม secp256k1’s

บรรทัดที่ 8 : Function สำหรับคำนวณ ค่า Gas มี่ทั้งหมด 3 ระดับคือ low,medium,hight โดยจะ Return ออกมาเป็นหน่วย Gwei

บรรทัดที่ 18 : สร้าง Funciton สำหรับ โอน Ether

บรรทัดที่ 19 : ดึงค่า Gas จาก Function ที่สร้างไว้

บรรทัดที่ 20 : แปลงหน่วย Gas (Gwei) เป็น หน่วย Wei

บรรทัดที่ 21 : ดึงจำนวน Transaction ของ Account ออกมา ซึ่งจะเพิ่มขึ้นทุกครั้ง (Increment) ที่มีการทำ Transaction

บรรทัด 22 : กำหนดจำนวน Ether ที่ต้องการโอน โดยมีหน่วย Wei

บรรทัดที่ 24 : กำหนดค่า nonce โดยใช้ค่า ที่ดึงมาจาก Transaction Count แล้วแปลงเป็น Hex อีกที

nonce เอาไว้อ้างอิง Transaction ซึ่งถ้าการโอนมีความผิดพลาด ก็จะทำ Transaction นี้อีกครั้ง ซึ่งถ้าโอนหลายๆครั้ง ติดต่อกัน แล้วค่า nonce ซ้ำกัน จะขึ้น Error ว่า 
Error: Returned error: nonce too low

บรรทัดที่ 25 : ดึงค่า Gas จาก Function ที่สร้างไว้ แล้วแปลงเป็น Hex

บรรทัดที่ 26 : จำนวน Gas ที่ยอมจ่ายสูงสุด ซึ่งถ้ามากกว่าที่ต้องไว้ จะ Error

บรรทัดที่ 27 : Wallet ของปลายทาง ที่ต้องการจะโอนให้

บรรทัดที่ 28 : จำนวน Ether ที่อยู่ในรูปแบบ Hex

บรรทัดที่ 29 : เราสามารถแนบข้อมูล ไปกับ Transaction ได้ซึ่งจะอยู่ในรูปแบบ Hex โดยจะคิดค่า Gas ตามขนาดของข้อมูล

บรรทัดที่ 30 : เลือก Node ของ Ethereum // mainnet: 1, ropsten: 3

บรรทัดที่ 33: นำไปเข้ารหัส (rlp)ให้อยู่ในรูปแบบของ Buffer

raw:
[ <Buffer 03>,
<Buffer 08 26 29 9e 00>,
<Buffer 52 08>,
<Buffer cf 4c a3 55 ec 55 72 4d ec 46 40 4b 36 0b c0 0e 51 6f 6e 8f>,
<Buffer 01 63 45 78 5d 8a 00 00>,
<Buffer >,
<Buffer 1c>,
<Buffer >,
<Buffer >

บรรทัดที่ 34: ทำการ Sign Transaction โดยใช้ Private Key ที่อยู่ในรูปแบบของ Buffer

บรรทัดที่ 35: นำ Buffer มาเข้ารหัสอีกที เพื่อ รวมกันเป็นอันเดียว

<Buffer f8 6c 03 85 09 50 2f 90 00 82 52 08 94 cf 4c a3 55 ec 55 72 4d ec 46 40 4b 36 0b c0 0e 51 6f 6e 8f 88 01 63 45 78 5d 8a 00 00 80 29 a0 1d 94 f4 24
c0 … >

บรรทัดที่ 36 : นำ ‘0x’ ไปต่อกับ Buffer ที่ถูกเข้าระหัสให้อยู่ในรูปแบบ Hex

0xf86c0385098bca5a0082520894cf4ca355ec55724dec46404b360bc00e516f6e8f88016345785d8a0000802aa094d7a767404cf4353f4061df
c6fc194b4020b3787e9a96c7b19d3e510a273c0

บรรทัดที่ 37 : ทำการ Broadcast Transaction นี้ไปทุกๆโหนด บน Ethereum Network (Ropsten Network)

หรือจะนำ Hex ที่ได้นี้ ไป Sign Transaction บนเว็บ Etherscan.io ก็ได้

https://ropsten.etherscan.io/pushTx

ผลลัพธ์

ตามไปดูบน Etherscan.io

https://ropsten.etherscan.io/tx/0xed16be687b38f2f2318904f4d0147c8f01f6b1ee3e1b72597b6b19ac8c589bcd

Smart Contract

อธิบายสั้นๆ

Smart Contract แปลตรงตัวคือ “สัญญาอัจฉริยะ” สำหรับคำว่า “สัญญา” ใน Blockchain หมายถึง เราสามารถ เขียน Function ขึ้นมา เพื่อสั่งงาน บางอย่างได้ และโปรแกรมที่เราเขียนขึ้นมา จะทำตามเงื่อนไข ที่เราได้สั่งไว้ โดยคำสั่งนั้น จะถูกเก็บไว้บน Blockchain

ทดสอบ เชื่อมต่อ Web3.js กับ Smart Contract

เริ่มแรก ผมจะได้ทำการ Copy ตัว Contract ABI ของ OMG มา หรือเป็นตัวอื่นก็ได้ ขอแค่เป็น ERC-20 Token

ABI คือ function ต่างๆ ของ Contract ที่เราสร้างขึ้นมา ซึ่งจะอยู่ในรูปแบบของ Json

https://etherscan.io/address/0xd26114cd6EE289AccF82350c8d8487fedB8A0C07#code

ลองดึง ชื่อ Token และจำนวนเหรียญ มาแสดง ผ่าน methods name และ totalSupply

ผลลัพธ์ที่ได้คือ

Token Name: OMGToken Total Supply: 140245398.245132780789239631

เมื่อเอาไปเช็คที่ Etherscan.io จะเห็นว่าเท่ากันเป๊ะ

https://etherscan.io/token/0xd26114cd6EE289AccF82350c8d8487fedB8A0C07

ทดสอบ สร้างเว็บไซต์สำหรับซื้อสินค้า Web3.js + MataMask

สิ่งที่ต้องทำ

  • สร้างหน้าเว็บไซต์ ง่ายๆ 1 หน้า
  • เชื่อมต่อ Web3.js กับ Matamask
  • เขียนโค้ดเพื่อเช็ค Transaction โดยมีเงื่อนไขว่า ถ้ายอดเงินที่โอนมา ตรงกับ ราคาสินค้าที่ตั้งไว้ ให้แสดง ที่อยู่ของ wallet และ จำนวน ที่โอนมา

เริ่มแรก สร้างหน้าเว็บไซต์ง่ายๆ ขึ้นมาหนึ่งหน้า

สามารถ ติดตั้งผ่าน web3.js ผ่าน npm หรือ ดาวน์โหลด มาใช้งานก็ได้

สร้างไฟล์ app.js ขึ้นมาแล้วพิมพ์โค้ดตามนี้

บรรทัดที่ 2 : ตรวจสอบว่า มีการติดตั้ง Metamask แล้วหรือยัง ถ้าติดตั้งแล้ว ให้ใช้ Provider ที่ได้เลือกไว้ ถ้าไม่ได้ติดตั้ง ก็จะเลือก Network ที่กำหนดไว้แทน

จากนั้นกำหนดให้ เมื่อมีการคลิ๊กที่ปุ่ม ซื้อ ให้เปิด Metamask ขึ้นมา พร้อมกับ Wallet ปลายทาง และ จำนวน ที่ได้กำหนดไว้

จะได้โค้ดตามนี้

อธิบายโค้ด

บรรทัดที่ 9 : เมื่อมีการกดปุ่มสั่งซื้อ

บรรทัดที่ 10 : กำหนด wallet สำหรับ รับ Ether (ของร้านค้า)

บรรทัดที่ 11 : กำหนดราคา ให้ กบ ตัวละ 0.5 Ether

บรรทัดที่ 12: ถึง บรรทัดที่ 15 : สร้าง Object เตรียมสำหรับการโอน โดยจะมีการ Submit Transaction เมื่อกดปุ่มโอนจาก Metamask

ขั้นตอนสุดท้าย เขียน Script เพื่อเช็คเมื่อมี การโอนเข้ามา (ใช้โค้ดในตอนแรกมาดัดแปลงเพิ่มเติม)

เพื่มโค้ดในส่วนของการเช็คราคา

ไม่พูดเยอะ //เจ็บคอ ดู Demo เลยดีกว่า

gif

Source Code https://github.com/niawjunior/kob-shop

จบแล้วววว -v-

อ้างอิง

pasupol bunsaen

Written by

javascript ❤️firebase ❤️angular ❤️ vue