iT邦幫忙

2021 iThome 鐵人賽

DAY 15
2
Modern Web

All In One NFT Website Development系列 第 15

Day 15【web3.js】一袋米要扛幾樓

【前言】
這兩天的文章都是 web3.js 的學習筆記,大部分內容都來自他們的官方文件!之後還會有 ethers.js 的學習筆記。然後延伸探討到底要使用什麼方法來取得 Token Owner 以及 Account Balance 比較好。不過看了越多官方文件就越痛苦,更不用說還要實作…

【web3.js】
we3.js 是一個 JavaScript 的套裝 library,裡面擁有許多函數或介面可以讓開發者利用 HTTP, IPC 或 WebSocket 遠端連動以太坊上的節點,進而取得鏈上訊息、合約資料、帳戶資訊。甚至是在取得使用者登入簽名後進行交易動作。

下載套件:

npm install web3
yarn add web3

we3.js 的四個重要模組:

  • web3-eth 用於以太坊的區塊鏈以及智能合約
  • web3-shh 用於 **Whisper 通訊協議(Ehtereum’s inter-application communication protocol)**和 在 P2P 對等式網路中連動或播送
  • web3-bzz 用於 Swarm 記帳協議(Swarm Accounting Protocol,SWAP)去中心化的資料儲存
  • web3-utils 提供 Dapp 開發者可能會需要用到的功能函數。

因為篇幅有限所以我這幾天介紹 web3.js 的文章重點會放在 web3-eth 以及 web3-utils,如果明年我還有參加鐵人賽也許會更加詳細的介紹這些模組!

如果在支援 MetaMask 的瀏覽器中有下載 MetaMask,便可以透過 EIP-1193: Ethereum Provider JavaScript API 這項協定來利用 window.ethereum 來達到同樣目的!這也是為什麼在我之前【連動 MetaMask】的系列文章之中有透過這個方法得到登入者資料過。

EIP-1193: Ethereum Provider JavaScript API

利用以下的程式碼中的 givenProvider 測試是不是已經取得以太坊連動!如果變數 web3 回傳 null 的話表示還沒連上。

// In Node.js use: const Web3 = require('web3');

const web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");

【we3.eth】
web3-eth 是一個用於以太坊的區塊鏈以及智能合約的模組,我們在取得連動之後就可以透過 getAccounts 取得當前節點的地址資料。

const Web3 = require('web3'); // In Node.js
web3.eth.getAccounts(console.log);
> ["0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe" ,"0x85F43D8a49eeB85d32Cf465507DD71d507100C1d"]

要注意的是透過 we3.js 回傳的所有地址資料都是核對和地址(checksum addresses),也就是說裡面可能包含一些大寫字母以及一些小寫字母。如果想要規避錯誤檢測的話可以把整個字串轉為小寫。之前【連動 MetaMask】的系列文章之中有提到過這篇文章!

How can I check if an Ethereum address is valid?

【we3.eth.accounts】
web3.eth.accounts 做為以太坊帳戶的變數型態,可以來核准交易或傳遞資料。

var Accounts = require('web3-eth-accounts');

// Passing in the eth or web3 package is necessary to allow retrieving chainId, gasPrice and nonce automatically
// for accounts.signTransaction().
var accounts = new Accounts('ws://localhost:8546');

web3.eth.accounts.create([entropy]) 可以產生一個以太坊帳戶的物件。

web3.eth.accounts.create([entropy]); // Generates an account object with private key and public key.
// example
web3.eth.accounts.create(web3.utils.randomHex(32));
> {
    address: "0xe78150FaCD36E8EB00291e251424a0515AA1FF05",
    privateKey: "0xcc505ee6067fba3f6fc2050643379e190e087aeffe5d958ab9f2f3ed3800fa4e",
    signTransaction: function(tx){...},
    sign: function(data){...},
    encrypt: function(password){...}
}

Parameters:
entropy - String (optional): 可以使用任意字串來增加亂度,想要使用這個參數的話至少要提供 32 個字元的字串。如果沒有的話會自動使用 randomhex() 產生隨意字串。
Returns:
Object - 此以太坊帳戶物件會包含以下資料結構:

  • address - string: 以太坊帳號地址。
  • privateKey - string: 帳號私鑰。為了安全問題,私鑰永遠不可以被分享或儲存在未加密過的儲存空間,並且在使用後需要確保這個值是 null 的。
  • signTransaction(tx [, callback]) - Function: 此函數用於簽核交易,詳細可見 web3.eth.accounts.signTransaction()
  • sign(data) - Function: 此函數用於簽核交易,詳細可見 web3.eth.accounts.signTransaction()

web3.eth.accounts.wallet 此變數型態可包含已記錄的多個以太坊帳戶資料,這些帳戶可以被用在 web3.eth.accounts.signTransaction()

web3.eth.accounts.wallet;
> Wallet {
    0: {...}, // account by index
    "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55": {...},  // same account by address
    "0xf0109fc8df283027b6285cc889f5aa624eac1f55": {...},  // same account by address lowercase
    1: {...},
    "0xD0122fC8DF283027b6285cc889F5aA624EaC1d23": {...},
    "0xd0122fc8df283027b6285cc889f5aa624eac1d23": {...},

    add: function(){}, 
		// Adds an account using a private key or account object to the wallet.
		// Return The added account(object)
    remove: function(){}, 
		// Removes an account from the wallet.
		// Return a Boolean(true if the wallet was removed)
    save: function(){},
		// Stores the wallet encrypted and as string in local storage.
		// Return a Boolean
    load: function(){},
		// Loads a wallet from local storage and decrypts it.
		// Return The wallet(object)
    clear: function(){},
		// Securely empties the wallet and removes all its accounts.
		// Return The wallet(object)

    length: 2,
}

【we3.eth.personal】
web3-eth-personal 這個套件可以讓開發者與以太坊節點的帳戶連動,節點的決定由 provider 提供。要注意的是這個套件裡面的函數會回傳許多敏感資訊像是密碼或者私鑰!

// or using the web3 umbrella package

var Web3 = require('web3');
var web3 = new Web3(Web3.givenProvider || 'ws://some.local-or-remote.node:8546');

// -> web3.eth.personal
// Warning!! Never call these functions over a unsecured Websocket or HTTP provider, as your password will be sent in plain text!

我們可以利用 setProvider 來設定當前想要的 provider

// Example: Local Geth Node
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
// Example: Remote Node Provider
var web3 = new Web3("https://eth-mainnet.alchemyapi.io/v2/your-api-key");

provider 其實就是 we3 如何與區塊鏈聯繫,也就是一個具有訪問以及連動區塊鏈的能力的節點。其會使用一個 JSON-RPC requests 並且回傳一個 response。通常會被遞交一個 request 給 HTTP 或 IPC socket based server。

web3.eth.personal.sign 此函數可產出 Ethereum 特定的 signature

web3.eth.personal.sign(dataToSign, address, password [, callback])sign
// Warning!! Sending your account password over an unsecured HTTP RPC connection is highly unsecure.

// example
web3.eth.personal.sign(web3.utils.utf8ToHex("Hello world"), "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe", "test password!")
.then(console.log);
> "0x30755ed65396facf86c53e6217c52b4daebe72aa4941d89635409de4c9c7f9466d4e9aaec7977f05e923889b33c0d0dd27d7226b6e6f56ce737465c5cfd04be400"

Parameters:

  1. String - Data to sign. If String it will be converted using web3.utils.utf8ToHex.
  2. String - Address to sign data with.
  3. String - The password of the account to sign data with.
  4. Function - (optional) Optional callback, returns an error object as first parameter and the result as second.
    Returns:
    Promise returns String - The signature.

web3.eth.personal.getAccounts 會回傳一個此節點控制的地址們的陣列。利用 provider 和 calling RPC method personal_listAccounts。使用 web3.eth.accounts.create() 不會在這個 list 裡面增加帳號。需要使用 web3.eth.personal.newAccount() 才能達到在 list 裡面增加帳號的效果。

web3.eth.personal.getAccounts([callback])

// example
web3.eth.personal.getAccounts()
.then(console.log);
> ["0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe", "0xDCc6960376d6C6dEa93647383FfB245CfCed97Cf"]

此函數和 web3.eth.getAccounts() 的結果是一樣的,除非是 calls RPC method eth_accounts。

Returns:
Promise<Array> - 一個此節點控制的地址們組成的陣列。

【小結】
今天就簡單介紹了幾個 we3.eth.accounts 以及 we3.eth.personal 的相關函數和基本資訊,明天會接續介紹 we3.eth.contractweb3.utis 這兩個套件!

【參考資料】
web3.js - Ethereum JavaScript API - web3.js 1.0.0 documentation


上一篇
Day 14【連動 MetaMask - Front-End Request and Fetch】Modern problems require modern solutions
下一篇
Day 16【web3.js】I KNOW BINARY AND HEXADECIMAL
系列文
All In One NFT Website Development32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言