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。谢谢!

相关推荐
程序员爱钓鱼12 分钟前
Rust String 与 &str 详解:字符串所有权、借用与转换
前端·后端·rust
码农学院17 分钟前
GEO与SEO协同:从传统搜索到生成式搜索的平滑迁移路径
服务器·前端·python
咩咩啃树皮9 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
阳光是sunny9 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端
触底反弹9 小时前
一文搞懂 Tailwind CSS 弹性布局:从原理到实战
前端·css·html
阳光是sunny9 小时前
从链到图:LangGraph 入门基础全解析
前端·人工智能·后端
小林ixn10 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
REDcker10 小时前
显示分辨率标准对照详解
前端·网络·分辨率·显示·屏幕
এ慕ོ冬℘゜10 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
武子康11 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端