Next.js+Wagmi+rainbowkit构建以太坊合约交互模版

前言 三年前写了一个类似的模板juejin.cn/post/713722... ,现在来看,已经方式已经过时,组装的也有些复杂,最近查看了各个repo,以最轻量化的方式来构造一个模板来快速启动一个以太坊dapp开发的项目框架。

技术栈

  1. Next.js v15
  2. Wagmi v2
  3. Rainbowkit

项目介绍

模板地址:github.com/0xverin/Nex...

bash 复制代码
├── app/                    # Next.js 应用目录
├── config/                 # 配置文件
│   └── contracts/          # 合约相关配置
│       ├── abi/            # 合约 ABI
│       └── addresses.ts    # 合约地址
├── hooks/                  # 自定义 React Hooks
│   └── contracts/          # 合约相关 hooks
├── utils/                  # 工具函数
│   ├── addressHelpers.ts   # 地址相关工具
│   └── contractHelpers.ts  # 合约相关工具
└── ...

本地运行

首先去WalletConnect Cloud申请一个project id,然后根据env.example创建一个本地env.local,写入NEXT_PUBLIC_PROJECT_ID=YOUR_PROJECT_ID。

复制代码
pnpm install
pnpm dev

wagmi配置

主要是根据官网教程自行配置:

javascript 复制代码
import { getDefaultConfig, WalletList } from "@rainbow-me/rainbowkit";
import { http } from "wagmi";
import { mainnet, sepolia } from "wagmi/chains";
import { metaMaskWallet, okxWallet } from "@rainbow-me/rainbowkit/wallets";

const wallets: WalletList = [
  {
    groupName: "Wallets",
    wallets: [okxWallet, metaMaskWallet],
  },
];
const chains = [mainnet, sepolia] as const;

const metadata = {
  name: "Nextjs Wagmi Quickstart",
  projectId: process.env.NEXT_PUBLIC_PROJECT_ID || "",
};
const config = getDefaultConfig({
  appName: metadata.name,
  projectId: metadata.projectId,
  chains,
  transports: {
    [chains[0].id]: http(),
    [chains[1].id]: http(),
  },
  ssr: true,
  wallets,
});

export const wagmiConfig = config;

export const defaultNetwork = chains[1];

合约调用封装:

读合约:

typescript 复制代码
// read example
export const useReadTestTokenContract = (address?: Address) => {
  const chainId = useChainId();
  const contract = getTestTokenContract(chainId);

  const contracts = [
    {
      ...contract,
      functionName: "balanceOf",
      args: [address],
    },
    {
      ...contract,
      functionName: "decimals",
    },
    {
      ...contract,
      functionName: "name",
    },
    {
      ...contract,
      functionName: "symbol",
    },
    {
      ...contract,
      functionName: "totalSupply",
    },
  ];

  const { data, error, isLoading, isError, refetch } = useReadContracts({
    contracts: contracts.map((contract) => ({
      ...contract,
      abi: contract.abi as Abi,
    })),
    query: {
      enabled: !!address,
    },
  });

  const [
    balanceOfAddress = BigInt(0),
    decimals = 0,
    name = "",
    symbol = "",
    totalSupply = BigInt(0),
  ] = data?.map((d) => d.result) ?? [];

  const res = {
    balanceOfAddress,
    decimals,
    name,
    symbol,
    totalSupply,
  };
  return {
    data: res,
    error,
    isLoading,
    isError,
    refetch,
  };
};

写合约:

ini 复制代码
// write example
export const useMintTestToken = () => {
  const chainId = useChainId();
  const contract = getTestTokenContract(chainId);
  const {
    data: hash,
    isPending,
    writeContractAsync,
    error: executionError,
  } = useWriteContract();
  const {
    isLoading: isConfirming,
    isSuccess: isConfirmed,
    error: callError,
  } = useWaitForTransactionReceipt({
    hash,
  });
  const write = async (address: Address, amount: bigint) => {
    return await writeContractAsync({
      ...contract,
      functionName: "mint",
      args: [address, amount],
    });
  };
  return {
    isPending,
    hash,
    writeContract: write,
    executionError,
    isConfirming,
    isConfirmed,
    callError,
  };
};

基本上这两个简单封装能覆盖大部分的合约交互,后续可能会更新更多的case,比如multicall等等

这个template没有使用css包和其他复杂的包,只封装合约调用,对于合约拿到的数据需要再处理的工具函数也没有添加,可能后续会添加,目的是让有些强迫症的开发用起来舒服,比如:

  1. 我不想封装一堆provider,弄的很繁琐,wagmi v2版本已经做了很多封装。
  2. 我不想用这个ui组件,可能有的人喜欢elemnt-ui,有的人喜欢shadcn-ui。
  3. 使用rainbowkit钱包组件主要是看在他轻量化也能自定义,虽然现在reown很丰富,但是他有些功能没法自定义,我可能就需要一个hooks,但是他的hooks在触发的时候非要有一个自己的frame page的广告,我很反感。

demo演示

nextjs-wagmi-quick-start.vercel.app/

如果觉得好用,还请给个star。谢谢!

相关推荐
青皮桔27 分钟前
CSS实现百分比水柱图
前端·css
影子信息32 分钟前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月33 分钟前
1.vue权衡的艺术
前端·vue.js·开源
样子201837 分钟前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿38 分钟前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
链上Sniper2 小时前
智能合约状态快照技术:实现 EVM 状态的快速同步与回滚
java·大数据·linux·运维·web3·区块链·智能合约
孤水寒月2 小时前
给自己网站增加一个免费的AI助手,纯HTML
前端·人工智能·html
CoderLiu2 小时前
用这个MCP,只给大模型一个figma链接就能直接导出图片,还能自动压缩上传?
前端·llm·mcp
伍哥的传说2 小时前
鸿蒙系统(HarmonyOS)应用开发之实现电子签名效果
开发语言·前端·华为·harmonyos·鸿蒙·鸿蒙系统
海的诗篇_2 小时前
前端开发面试题总结-原生小程序部分
前端·javascript·面试·小程序·vue·html