uniapp 跨平台开发中集成以太坊全指南,从环境搭建到智能合约交互

时间: 2026-02-24 9:18 阅读数: 7人阅读

随着区块链技术的飞速发展,去中心化应用(DApps)正逐渐成为互联网领域的新热点,而 UniApp 凭借其“一次开发,多端发布”的优势,成为了许多开发者构建跨平台应用的首选,将 UniApp 与以太坊这样的主流区块链平台相结合,可以让我们轻松构建能够与区块链交互的跨平台 DApps,本文将详细介绍如何在 UniApp 项目中调用以太坊,包括环境搭建、钱包连接、数据交互及智能合约调用等关键步骤。

准备工作:开发环境与依赖

在开始之前,我们需要准备以下环境和工具:

  1. Node.js 和 npm/yarn:确保你的系统已安装 Node.js(建议 LTS 版本)和相应的包管理器。
  2. HBuilderX:UniApp 的官方 IDE,提供了完善的开发、调试和打包功能。
  3. MetaMask 钱包插件:在浏览器(如 Chrome、Firefox)中安装 MetaMask 扩展,这是与以太坊交互最常用的钱包,在 UniApp 的 H5 端调试时,浏览器需要安装 MetaMask。
  4. 以太坊节点或 Infura/Alchemy 等 RPC 服务:你需要连接到一个以太坊节点来读取链上数据和发送交易,可以使用本地节点(如 Geth),但对于开发来说,使用 Infura 或 Alchemy 提供的免费 RPC 服务更为便捷。

核心库的选择与集成

在 UniApp 中调用以太坊,通常依赖于 JavaScript 库,目前最主流和推荐的是 web3.js (v4.x+) 或 ethers.js,两者功能强大,但 ethers.js 以其更现代的 API、更小的体积和更好的 TypeScript 支持逐渐受到青睐,本文将以 ethers.js 为例进行讲解。

  1. 安装 ethers.js随机配图

strong>: 在你的 UniApp 项目根目录下,打开终端,运行以下命令安装 ethers.js

npm install ethers
# 或者
yadd add ethers
  • 配置 uni-app 项目以支持 npm: 在 HBuilderX 中,右键点击项目根目录,选择“显示 npm 模块”,然后确保 ethers 已正确显示,如果项目没有 node_modules 文件夹,HBuilderX 可能会提示你构建 npm。

  • 连接以太坊钱包(以 MetaMask 为例)

    DApp 与区块链交互的第一步通常是连接用户的钱包,在 UniApp 的 H5 端,我们可以通过 window.ethereum 对象(由 MetaMask 注入)来实现。

    1. 检查并请求账户授权: 在页面的 JavaScript 代码中,你可以编写如下函数来连接钱包:

      // 在 pages/index/index.vue 或其他页面中
      async connectWallet() {
        try {
          // 检查浏览器是否安装了以太坊提供者(如 MetaMask)
          if (window.ethereum) {
            // 请求用户授权连接钱包
            const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
            if (accounts.length > 0) {
              this.currentAccount = accounts[0];
              console.log('已连接钱包:', this.currentAccount);
              // 可以在这里初始化 web3 或 ethers provider
              this.initProvider();
            }
          } else {
            uni.showToast({
              title: '请安装 MetaMask 钱包',
              icon: 'none'
            });
          }
        } catch (error) {
          console.error('连接钱包失败:', error);
          uni.showToast({
            title: '连接钱包失败',
            icon: 'none'
          });
        }
      },
    2. 初始化 Ethers Provider: 连接成功后,我们可以使用 window.ethereum 创建一个 Ethers.js 的 Provider 对象,这是与以太坊网络交互的入口。

      initProvider() {
        if (window.ethereum) {
          // 使用 Ethers.js 的 BrowserProvider 包装 window.ethereum
          this.provider = new ethers.BrowserProvider(window.ethereum);
          console.log('Ethers Provider 初始化成功:', this.provider);
        }
      },

    注意

    • 在 App 端和小程序端,由于浏览器环境的限制,直接使用 window.ethereum 是不可行的,通常需要集成第三方 SDK(如 uni-web3-sdkuni-ethers,这类 SDK 可能需要封装原生插件或提供特定的适配方案)或引导用户使用外部浏览器(如 DAppBrowser)打开链接进行交互,这部分相对复杂,可能需要根据具体平台进行适配。

    • 处理账户变化:监听 accountsChanged 事件,以便在用户切换账户时更新应用状态。

      // 在 initProvider 中或连接成功后添加
      if (window.ethereum) {
        window.ethereum.on('accountsChanged', (accounts) => {
          if (accounts.length === 0) {
            // 用户断开了连接
            this.currentAccount = null;
            console.log('用户已断开钱包连接');
          } else {
            // 用户切换了账户
            this.currentAccount = accounts[0];
            console.log('用户切换账户至:', this.currentAccount);
          }
        });
      }

    读取以太坊链上数据

    有了 Provider 对象,我们就可以轻松读取以太坊链上的数据,例如获取账户余额、查询区块信息、调用只读的智能合约方法等。

    1. 获取账户余额

      async getBalance() {
        if (!this.provider || !this.currentAccount) {
          uni.showToast({
            title: '请先连接钱包',
            icon: 'none'
          });
          return;
        }
        try {
          const balance = await this.provider.getBalance(this.currentAccount);
          // ethers.js 的 BigNumber 需要转换为可读格式,如 Ether
          const balanceInEther = ethers.formatEther(balance);
          this.balance = balanceInEther;
          console.log('账户余额:', balanceInEther, 'ETH');
        } catch (error) {
          console.error('获取余额失败:', error);
        }
      },
    2. 查询智能合约只读方法: 假设我们有一个已部署的智能合约,我们可以使用 Contract 对象来调用其只读(viewpure)方法。

      // 假设这是你的智能合约 ABI(Application Binary Interface)的一部分
      const contractABI = [
        // 一个获取某个地址代币余额的函数
        "function balanceOf(address owner) view returns (uint256)"
      ];
      // 合约地址
      const contractAddress = "0x...YourContractAddress...";
      async queryContractReadMethod() {
        if (!this.provider) {
          uni.showToast({
            title: 'Provider 未初始化',
            icon: 'none'
          });
          return;
        }
        try {
          const contract = new ethers.Contract(contractAddress, contractABI, this.provider);
          const balance = await contract.balanceOf(this.currentAccount);
          const formattedBalance = ethers.formatEther(balance);
          console.log('合约查询结果:', formattedBalance);
          uni.showToast({
            title: `查询成功,余额: ${formattedBalance}`,
            icon: 'success'
          });
        } catch (error) {
          console.error('合约查询失败:', error);
        }
      },

    发送交易与调用智能合约写方法

    与区块链进行写交互(如转账、调用智能合约的修改方法)需要用户使用钱包签名并支付 Gas 费。

    1. 获取签名者 (Signer): 发送交易需要 Signer 对象,它代表一个能够签名的账户。

      async getSigner() {
        if (!this.provider) {
          uni.showToast({
            title: 'Provider 未初始化',
            icon: 'none'
          });
          return null;
        }
        try {
          const signer = await this.provider.getSigner();
          console.log('Signer 获取成功:', signer);
          return signer;
        } catch (error) {
          console.error('获取 Signer 失败:', error);
          return null;
        }
      },
    2. 发送以太坊转账

      async sendTransaction(toAddress, amountInEther) {
        if (!this.currentAccount) {
          uni.showToast({
            title: '请先连接钱包',
            icon: 'none'
          });
          return;
        }
        try {
          const signer = await this.getSigner();
          if (!signer) return;
          const tx = {
            to: toAddress,
            value: ethers.parseEther(amountInEther) // 将 ETH 转换为 wei
          };
          const txResponse = await signer.sendTransaction(tx);
          console.log('交易已发送,等待确认:', txResponse.hash);
          uni.showLoading({
            title: '交易中,请稍候...'
          });
          // 等待交易被确认
          const txReceipt