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

投稿 2026-02-11 23:42 点击数: 5

随着区块链技术的飞速发展,去中心化应用(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: 在你的 UniApp 项目根目录下,打开终端,运行以下命令安装 ethers.js

    npm install ethers
    # 或者
    yadd add ethers
  2. 配置 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.cu
    随机配图
    rrentAccount); } }); }

读取以太坊链上数据

有了 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