【前言】
嗨嗨感謝大家願意看到這裡,接下來要說的是前端的呼叫以及資料傳遞。今天的內容大部份都參考來自 Amaury Martiny 的 One-click Login with Blockchain: A MetaMask Tutorial!終於又可以回來用 web3.js
了,果然現代問題還是要用現代手段解決, web3.js
和 MetaMask@onboarding
是我的好朋友阿!
【Web3.js】
這裡我們會使用到 JavaScript library web3.js
來引用 MetaMask 的相關 api。相關的介紹會在之後再做敘述!
npm install web3
import Web3 from 'web3';
web3.js - Ethereum JavaScript API - web3.js 1.0.0 documentation
【Front-End Request and Fetch】
在這邊首先使用到 fetch 的功能來新增資料,需要注意的是要先在 .env 宣告 REACT_APP_BACKEND_URL=http://localhost:8000/api
。
const handleSignup = (publicAddress) =>
fetch(`${process.env.REACT_APP_BACKEND_URL}/users`, {
body: JSON.stringify({ publicAddress }),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
}).then((response) => response.json());
這裡可以跳出 MetaMask 的登入介面並且顯示登入訊息,在取得 publicAddress
以及 nonce
之後顯示出來。詳細的步驟解釋可以回去看 Day 10 有提到的 Login Flow。
const handleSignMessage = ({ publicAddress, nonce }) => {
return new Promise((resolve, reject) =>
web3.personal.sign(
web3.fromUtf8(`I am signing my one-time nonce: ${nonce}`),
publicAddress,
(err, signature) => {
if (err) return reject(err);
return resolve({ publicAddress, signature });
}
)
);
};
在 authenticate
之中是傳出 publicAddress
以及 signature
,這將會在後端轉譯 signature
後比較這兩者是否相同,來判斷是不是登入成功。
const handleAuthenticate = ({ publicAddress, signature }) =>
fetch(`${process.env.REACT_APP_BACKEND_URL}/auth`, {
body: JSON.stringify({ publicAddress, signature }),
headers: {
'Content-Type': 'application/json'
},
method: 'POST'
}).then(response => response.json());
將以上的函式放入按鈕的函數之中。
const handleClick = async () => {
...
const publicAddress = coinbase.toLowerCase();
setLoading(true);
// Look if user with current publicAddress is already present on backend
fetch(
`${process.env.REACT_APP_BACKEND_URL}/users?publicAddress=${publicAddress}`
)
.then((response) => response.json())
// If yes, retrieve it. If no, create it.
.then((users) =>
users.length ? users[0] : handleSignup(publicAddress)
)
// Popup MetaMask confirmation modal to sign message
.then(handleSignMessage)
// Send signature to backend on the /auth route
.then(handleAuthenticate)
// Pass accessToken back to parent component (to save it in localStorage)
.then(onLoggedIn)
.catch((err) => {
window.alert(err);
setIsLoading(false);
});
};
【小結】
這邊我寫的方法還是主要還是由 MetaMask Onboarding
為主,只是我目前還找不到方法在 MetaMask 的登入介面處顯示 personal.sign
的 message
來告訴使用者當前的 nonce
。這是比較可惜的地方,但是在後端的部分還是有紀錄每個人的登入資訊!
直到這裡就暫時結束登入系統的部分啦,接下來要開始學習 web.js 以及 ether.js 了!未來如果有用到相關的功能會隨時回來這邊做修改!
【參考資料】
One-click Login with Blockchain: A MetaMask Tutorial
Using Fetch - Web APIs | MDN
【在網站內部驗證 MetaMask 並讓使用者登入】
amaurym/login-with-metamask-demo: Demo project for "One-click Login with Blockchain: A MetaMask Tutorial"
Advanced Ethereum Dapp Series - Part 2 - React Hooks for Injected MetaMask, Web3.js and ethers.js
blockchain election dapp || part 2 react connectivity with metamask
MetaMask Tutorial: One-click Login With Blockchain Made Easy