《Lottery Dapp项目》-如何连接钱包

300 阅读4分钟

在彩票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"文件如下图所示: 07ad4bdf0088482ea8b9bdb68d0cd231.png

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>
        )}
        // 略
    )
}

32042c9e7d4ab56f2de07bfbd6b77b4c.png 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行:处理获取到的账户:

  1. 如果获取到了账户,则将第一个账户的地址存储到 Redux store 中。

  2. 如果没有获取到账户,则将 Redux store 中的钱包地址设置为空字符串,并报告一个错误,提示用户连接钱包。

第21行:错误处理,如果在执行过程中发生任何错误,都会被捕获并通过 reportError 函数报告出来。

现在刷新一下页面显示的是钱包的地址,保持钱包连接功能完成喽!