前言三年前写了一个类似的模板Nextjs+wagmi+rainbowkit构建的Dapp开发模板+使用案例,现在来看,有些方式已经过时,组装的也有些复杂,最近查看了各个repo,以最轻量化的方式来构造一个模板来快速启动一个以太坊dapp开发的项目框架,主要包括:钱包连接合约读写两个
前言
三年前写了一个类似的模板# Nextjs+wagmi+rainbowkit构建的Dapp开发模板+使用案例 ,现在来看,有些方式已经过时,组装的也有些复杂,最近查看了各个repo,以最轻量化的方式来构造一个模板来快速启动一个以太坊dapp开发的项目框架,主要包括:
两个基本功能。
技术栈
项目介绍
模板地址:<https://github.com/0xverin/Nextjs-Wagmi-QuickStart>
├── 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配置
主要是根据官网教程自行配置:
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];
合约调用封装:
读合约:
// 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,
};
};
写合约:
// 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包和其他复杂的包,只封装合约调用,对于合约拿到的数据需要再处理的工具函数也没有添加,可能后续会添加,目的是让有些强迫症的开发用起来舒服,比如:
demo演示
<https://nextjs-wagmi-quick-start.vercel.app/>
如果觉得好用,还请给个star。谢谢!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!