今天要來完成的是 Mint Button
並讓 MetaMask 送出交易,並與 Provider 連動,與我們在鏈上的合約完成互動,呼叫 mintForAudience()
這個函式,mint 複數張的 ERC1155 ticket 到使用者的地址中。
首先先梳理一下整個運作流程。
在這個 project 裡面,我使用了 React-router-dom 這個套件來使頁面載入的速度加快。
在 App.js
的程式中可以看到這樣的語法:
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
<Router>
<div className="App">
<Navbar />
<div className="content">
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/Mint/Audience">
<Mint />
</Route>
</Switch>
</div>
</div>
</Router>
其中 <Switch>
中的 <Route>
可以代表每一個頁面,其中的 path 代表著此頁面的路徑,例如 <Mint>
的絕對路徑就是:http://localhost:3000/Mint/Audience
)。
而我們如何在頁面中做出一個可以連結到此路徑的 link?其實很簡單,同樣
import {Link} from 'react-router-dom'
接著直接使用 Link tag 便可以讓這個連結指向你的 Route 的路徑。
<Link to={'Mint/Audience'}></Link>
而昨天我設計並完成了登入的介面,但是並沒有做出 Home 這個頁面,後來使用 Router 做出下方成果。
跳過XD!(這部分因為時間問題,我應該不會再做)
在頁面上顯示:Choose How Many Tickets You Want to Mint.
這邊簡單的設置了一個計數器(就是 javascript 基本課程會上的那種XD)
<div className="mint-Count">
<button className="plus" onClick={ () => setMintNum(mintNum - 1)}>-</button>
<div className="mint-num">{ mintNum }</div>
<button className="minus" onClick={ () => setMintNum(mintNum + 1)}>+</button>
</div>
宣告一個 useState:mintNum
,並在增減的時候使用 setMintNum(mintNum (operator) 1)
便可以達成增減的效果。
首先我使用了 web3.js 這個套件。web3js 是一個頗為古老的 js 套件,可以讓使用者與遠端的 Ethereum 區塊鏈互動,如送出交易、查看鏈上資訊等。
cd 到 project 裡面 console 輸入下面指令安裝套件
npm install web3
先宣告一些變數,provider、contractAddress 與 mumbai ID
const web3 = new Web3(Web3.givenProvider);
const ticketAddress = "0xfEFBA989dBf2027745262940F02C41193C90Af62";
const mumbaiId = 80001;
第一步是需要確認錢包是否連接,這時可以利用 Home page 傳過來的 accounts 來確定是不是目前是否有帳號連接。
const isConnected = Boolean(account2[0])
第一步是如果沒有連接,則跳出訊息,叫使用者 Connect。這邊使用 window.etherum 中的 networkVersion value,可以偵測 network 是否為我們指定的。如果不是的話,就送出 window.ethereum.request({ wallet_switchEthereumChain, params: [<network Items>]})
。
const switchNetwork = () => {
if (!isConnected) {
alert('Please connect to MetaMask!');
return;
}
if (window.ethereum.netWorkVersion !== mumbaiId){
try {
window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: web3.utils.toHex(mumbaiId) }]
});
}
catch (err) {
// This error code indicates that the chain has not been added to MetaMask
if (err.code === 4902) {
window.ethereum.request({
method: 'wallet_addEthereumChain',
params:
[{
chainName: 'Polygon Testnet',
chainId: web3.utils.toHex(mumbaiId),
nativeCurrency: { name: 'MATIC', decimals: 18, symbol: 'MATIC' },
rpcUrls: ['https://rpc-mumbai.maticvigil.com/']
}]
});
}
}
}
}
在先前介紹 Provider 時,我們知道單只有管理私鑰的 wallet 是不能自行送交易到 Ethereum 中的,需要透過 provider 來與區塊鏈互動。
因此需要透過 Web3.getProvider 可以讓我們得到 browser 中的 provider 是誰。
另外 Wallet 可以透過私鑰來簽屬(signature)交易,再透過 Provider 將這筆交易傳遞到全節點中。而與鏈上互動的方式可以分成兩種:
1. read:
若以 webjs 而言的話就是:
web3.contract.methods.Mymethod(parameters).call()
call function 並不會改動任何鏈上 storage 的資料,只會 return 鏈上儲存的資訊。
2. write:
web3.contract.methods.Mymethod(parameters).send()
send function 則可以改動鏈上的資料,也就代表會這筆交易會執行鏈上的 function。
而我們要使用的就是第二種方法。
const ticketContract = new web3.eth.Contract(abi, ticketAddress);
ticketContract.methods.mintForAudience(mintNum).send({
from: window.ethereum.selectedAddress
})
.on('error', (error, receipt) => {
// emit when there is an error
console.log(receipt);
})
透過上述的方式便可以讓使用者在按下 mint button 後成功的 mint 到 ticket 了!
最後一步應該是最有挑戰性的,但是最後發現其實很簡單。
我們在上一步中使用 contract.methods.function().send()
,而這個 method 事實上就會回傳我們想要的東西:transactionHash
,我們可以透過這個 hash 與 mumbai polygon 的網址做結合,便可以得到這個交易所在的位置!
.on('transactionHash', (hash) => {
setTxSend(true);
setTxLink(prefix + hash); // prefix="https://mumbai.polygonscan.com/tx/"
});
下面則是網頁的最終結果:
可以在 Polygon Scan 上看到成功 mint 了兩個 id=3 的 token!
今天的內容,除了 Switch network 還有 mint function 有參考 Stackoverflow 上的寫法外,算是我用手一行一行慢慢地刻出來的,有一種慢慢的把一個小孩培養長大的感覺XDD。
而且最後一點:讓交易的網址可以顯現出來其實是我的一個額外想法。因為原本我前陣子做的 project -- BAKAJOHN 的網頁在 mint 後並沒有產生任何反應,我自己覺得是非常不符合使用者體驗的。原本以為這個功能會特別難做,沒想到最後成功地做出來了,非常的開心!
雖然成功的寫出了我想要的流程,但是我覺得有一些細節我還是沒有處理的很好,例如在 send transaction 後,應該是要等到 transaction 成功的被包在一個區塊中(在 Polygon 上的狀態為 success),才能被顯現出來,而在等待途中應該用「Loading...」來顯示等待中。
另外也有很多關於 web3 provider 的功能我也尚未完全了解,希望可以透過這個專案再學到更多。且由於 webjs 算是一個頗為古老的函式庫,我在未來也需要學習用 etherjs 等較新的函式庫來進行開發會更為時宜。
若有文章內有任何錯誤的地方歡迎指點與討論!非常感謝!
歡迎贊助窮困潦倒大學生
0xd8538ea74825080c0c80B9B175f57e91Ff885Cb4