使用 UniApp 集成 Reown 与 Wagmi:轻松实现钱包连接与智能合约交互

125 阅读4分钟

Wagmi

wagmi 是一个基于 React 的区块链开发工具库,兼容JavascriptVue,简化了与 EVM 兼容链的交互逻辑,内置了常见的区块链操作钩子,支持多链和钱包集成。

主要功能

  • 基于 React Hooks 的 API 设计,简化状态管理
  • 内置钱包连接(MetaMask、Coinbase Wallet 等)
  • 智能合约交互封装(读 / 写操作、事件监听)
  • 多链支持与链切换管理
  • 交易状态跟踪与错误处理

Reown

Reown使构建者能够创建安全,用户友好和富有洞察力的钱包和应用程序UX。提供所有工具,以更快地启动和更智能地扩展。

主要功能

  • 支持多种钱包的无缝连接
  • 提供标准化的连接流程
  • 支持移动端和桌面端钱包
  • 管理多个应用的连接会话
  • 提供会话状态的实时同步
  • 支持会话的持久化存储
  • 支持主流区块链网络

集成教程

1.安装(以Vue+wagmi为示例)

pnpm add @reown/appkit @reown/appkit-adapter-wagmi @tanstack/vue-query @wagmi/vue viem

2.申请ProjectId

前往Reown仪表板并立即创建一个新项目申请ProjectId

3.将配置添加到项目

在utils中添加wagmiConfig.ts配置

import type { AppKitNetwork } from '@reown/appkit/networks'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { bsc, bscTestnet } from '@reown/appkit/networks'
//填写reown仪表板申请的projectId
export const projectId = import.meta.env.VITE_PROJECT_ID
// 通过walletconnect协议连接时 钱包应用显示的dapp信息
export const metadata = {
  name: 'AppKit',
  description: 'AppKit Example',
  url: 'http://192.168.0.209:9001',
  icons: ['https://avatars.githubusercontent.com/u/179229932'],
}
//以单链为示例 正式服使用线上链  其余使用测试链
export const network = import.meta.env.MODE === 'production' ? bsc : bscTestnet 
export const networks: [AppKitNetwork, ...AppKitNetwork[]] = [network]
//适配器为wagmi
export const wagmiAdapter = new WagmiAdapter({
  networks,
  projectId,
})

在app.vue中添加reown的弹框


<script lang="ts" setup>
  import {createAppKit} from '@reown/appkit/vue'
  import {metadata, networks, projectId, wagmiAdapter} from './utils/wagmiConfig'

  const modal = createAppKit({
    adapters: [wagmiAdapter],
    networks,
    projectId,
    metadata,
// --w3m-font-family基本字体系列string
// --w3m-accent用于按钮、图标、标签等的颜色。string
// --w3m-color-mix与默认颜色混合的颜色string
// --w3m-color-mix-strength“—w3m-color-mix” 应该混合的百分比number
// --w3m-font-size-master字体的基本像素大小。string
// --w3m-border-radius-master基本边框半径(以像素为单位)。string
// --w3m-z-index模态框的 z-index。number
    themeVariables: {
      '--w3m-accent': '#00BB7F',
      '--w3m-font-size-master': '10px',
    },
  })
</script>
<template></template>

main.ts中导入


import { VueQueryPlugin } from '@tanstack/vue-query'
import { WagmiPlugin } from '@wagmi/vue'
import { wagmiAdapter } from './utils/wagmiConfig'

export function createApp() {
...
//添加这两行
  app.use(VueQueryPlugin)  
  app.use(WagmiPlugin, { config: wagmiAdapter.wagmiConfig }) //使用@wagmi/vue的usexxx可以不用传入配置
...
}

以上就完成了导入库与配置

使用示例

1.使用appkit提供的web组件

<template>
<appkit-button />
</template>

点击按钮后的效果: image.png

2.与合约交互

<script setup lang="ts"> 
import { readContract } from '@wagmi/core'
import { erc20Abi } from 'viem' 
const USDTAddress = '0x...'
//查询代币精度 
//用@wagmi/vue提供的useReadContract也类似 我这边比较喜欢用core的方式
const data = readContract(wagmiAdapter.wagmiConfig,{ abi: erc20Abi, address: USDTAddress, functionName: 'symbol' }) </script>

以上就基本完成了reown+wagmi的导入与配置

遇到的问题

1.本地运行一切正常,打包后部署到服务器插件报错undefined ..-nodexxxx 错误

解决方案

vite.config.ts的build对象中添加该段代码可解决 这个方案是ai提供的我这边是可以解决这个问题

      rollupOptions: {
        output: {
          manualChunks: (id) => {
            if (!id || typeof id !== 'string')
              return 'vendor'
              // 统一路径分隔符
            const normalizedId = id.replace(/\\/g, '/')
            if (!normalizedId.includes('node_modules'))
              return
              // 处理 @scope/package 和普通包
            const match = normalizedId.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/)
            return match ? `vendor-${match[1].replace('@', '')}` : 'vendor'
          },
        },
      },

2.bigint报错

解决方案

vite.config.ts的build设置

  target: 'es2020',

3.部分老旧手机可能存在无法连接钱包 表现为reown提供的弹框连接时一直加载

解决方案

reown使用了Obejct.hasOwn() 部分谷歌内核低的手机会报错

image.png 可以通过导入corejs解决

pnpm add core-js

main.ts中导入(我暂时全量导入了,理论上是需要根据缺少什么去导入什么的,打包后包似乎大了1m左右)

import 'core-js/stable'

4.部分手机存在tp写入合约操作后获取hash但hash始终无法推送到区块链浏览器上

解决方案

/*
获取推荐最快的 gas 价格
@returns 返回包含 maxFeePerGas 和 maxPriorityFeePerGas 的对象
Gas 总价 = 基础费用(maxFeePerGas) + 优先级小费(maxPriorityFeePerGas)
*/
export async function getGasPrice() {
const fees = await estimateFeesPerGas(wagmiAdapter.wagmiConfig, {
chainId: networks[0].id // 替换为你实际使用的链 ID
});
return {
maxFeePerGas: fees.maxFeePerGas,
maxPriorityFeePerGas: fees.maxPriorityFeePerGas};
}