在彩票Dapp中连接钱包是非常重要的步骤,因为它允许用户与以太坊网络进行交互,购买彩票、支付费用等操作。通过连接钱包,用户可以使用其以太坊地址进行身份验证和交易签名。
实现connectWallet方法
创建services/blockchain.js,import如下内容。
import { store } from "@/store";
import { ethers } from "ethers";
import { globalActions } from "@/store/globalSlices";
import address from "@/artifacts/contractAddress.json";
import abi from "@/artifacts/contracts/DappLottery.sol/DappLottery.json";
import { toWei, fromWei } from "@/utils/index";
// redux方法
const { setWallet } = globalActions;
// 执行deploy命令后的生成的json
const contractAddress = address.address;
let tx, ethereum;
"@/artifacts/contractAddress.json"文件如下图所示:
toWei, fromWei方法用来转换单位,如下所示:
// 将输入的数字转换为以太币的 Wei 单位
export const toWei = (num) => ethers.parseEther(num.toString());
// 假设你有一个值为 1000000000000000000 的值,这是 1 Ether 的 Wei 表示
// 使用 fromWei 函数将这个值转换回 Ether
export const fromWei = (num) => ethers.utils.formatEther(num);
typeof window !== "undefined"为了确保当前环境是在浏览器环境中,
window.ethereum是MetaMask等以太坊钱包在浏览器窗口对象中的实例,通过检查ethereum是否存在,开发者可以确定用户是否安装了兼容的以太坊的钱包。我们在这里用的小狐狸钱包(MeteMask)。
之后,我们可以使用这个ethereum对象来进一步和以太坊网络交互。
if (typeof window !== "undefined") {
ethereum = window.ethereum;
}
connectWallet方法如下:
export const connectWallet = async () => {
try {
if (!ethereum) return reportError("Please install Mestmask");
const accounts = await ethereum.request({ method: "eth_requestAccounts" });
store.dispatch(setWallet(accounts[0]));
} catch (error) {
reportError(error);
}
};
const reportError = (error) => {
console.log("error.message:", error.message);
};
第3行:首先检查是否存在 ethereum 对象,也就是检查用户是否安装了 MetaMask 等支持以太坊的钱包插件。如果没有安装,则调用 reportError 函数并返回。
第4行:这里使用 ethereum.request 方法,传入 { method: "eth_requestAccounts" } 参数,这会触发一个弹出窗口,要求用户授权 Dapp 访问其以太坊账户。一旦用户授权,该方法将返回一个包含用户以太坊地址的数组。
第5行:将获取到的第一个以太坊地址保存到 Redux 的 store 中,方便后续在 Dapp 中使用。这里使用了 setWallet 这个 action creator 来更新 store 中的钱包地址。
第7行:如果在上述过程中发生任何错误,将会被捕获并传递给 reportError 函数进行处理。
然后去Navbar组件中设置connectWallet方法。
修改Navbar组件
// Navbar.jsx新添加代码如下:
import { useSelector } from "react-redux";
import { connectWallet } from "@/services/blockchain";
import { truncate } from "@/utils/index";
export const Navbar = () => {
const { wallet } = useSelector((state) => state.globalState);
return (
// 略
{wallet ? (
<div className=" bg-[#ea580c] text-white px-4 py-1 rounded-full">
{truncate(wallet, 4, 4, 11)}
</div>
) : (
<div className=" bg-[#ea580c] text-white px-4 py-1 rounded-full hover:bg-[#9a3412]">
<button onClick={connectWallet}>Connect Wallet</button>
</div>
)}
// 略
)
}
truncate方法用来截取钱包的address,只显示前四位后四位,中加用...省略。
truncate方法代码如下:
export const truncate = (text, startChars, endChars, maxLength) => {
if (text.length > maxLength) {
let start = text.substring(0, startChars);
let end = text.substring(text.length - endChars, text.length);
while (start.length + end.length < maxLength) {
start = start + ".";
}
return start + end;
}
return text;
};
此时连接钱包完成了,但还有一个问题。当我们刷新一下,按钮又回变成connect wallet。接下来实现保持钱包连接功能。
实现monitorWalletConnection方法
export const monitorWalletConnection = async () => {
try {
if (!ethereum) return reportError("Please install Mestmask");
const accounts = await ethereum.request({ method: "eth_accounts" });
window.ethereum.on("chainChanged", (chainId) => {
window.location.reload();
});
window.ethereum.on("accountsChanged", async (chainId) => {
store.dispatch(setWallet(accounts[0]));
await monitorWalletConnection();
});
if (accounts.length) {
store.dispatch(setWallet(accounts[0]));
} else {
store.dispatch(setWallet(""));
reportError("Please, connect wallet, no accounts found");
}
} catch (error) {
reportError(error);
}
};
monitorWalletConnection方法是用来监控钱包连接状态的方法。
第3行:检查是否安装了 MetaMask 钱包,如果没有安装 MetaMask,则返回一个错误报告,提示用户安装 MetaMask。
第4行:获取用户的以太坊账户, 使用 ethereum.request({ method: "eth_accounts" }) 方法获取用户的以太坊账户列表。
第6行和第10行都是监听钱包事件。
第6行:监听chainChanged 事件,当用户切换到不同的以太坊网络时,页面会自动刷新。
第10行:监听accountsChanged 事件,当用户切换账户或连接/断开钱包时,更新 Redux store 中的钱包地址。
第15行:处理获取到的账户:
-
如果获取到了账户,则将第一个账户的地址存储到 Redux store 中。
-
如果没有获取到账户,则将 Redux store 中的钱包地址设置为空字符串,并报告一个错误,提示用户连接钱包。
第21行:错误处理,如果在执行过程中发生任何错误,都会被捕获并通过 reportError 函数报告出来。
现在刷新一下页面显示的是钱包的地址,保持钱包连接功能完成喽!