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

相关推荐
gnip1 小时前
js上下文
前端·javascript
中草药z1 小时前
【Stream API】高效简化集合处理
java·前端·javascript·stream·parallelstream·并行流
不知名raver(学python版)1 小时前
npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR!
前端·npm·node.js
醉方休2 小时前
React中使用DDD(领域驱动设计)
前端·react.js·前端框架
excel2 小时前
📖 小说网站的预导航实战:link 预加载 + fetch + 前进后退全支持
前端
学习3人组2 小时前
React 样式隔离核心方法和最佳实践
前端·react.js·前端框架
世伟爱吗喽2 小时前
threejs入门学习日记
前端·javascript·three.js
朝阳5812 小时前
用 Rust + Actix-Web 打造“Hello, WebSocket!”——从握手到回声,只需 50 行代码
前端·websocket·rust
F2E_Zhangmo2 小时前
基于cornerstone3D的dicom影像浏览器 第五章 在Displayer四个角落显示信息
开发语言·前端·javascript