如何以最佳方式配置Solidity合约与React/Next.js前端的连接?
Solidity合约与React/Next.js前端连接的Hardhat/Truffle最优配置
一、Hardhat + React/Next.js 配置方案
1. 初始化Hardhat项目
npx hardhat init
选择JavaScript/TypeScript项目模板,按提示完成依赖安装。
2. 合约编译与部署
- 编写合约(示例:
contracts/SimpleStorage.sol),执行编译:
npx hardhat compile
编译完成后,artifacts/contracts目录会生成包含ABI和字节码的JSON文件。
- 编写部署脚本(
scripts/deploy.js):
const hre = require("hardhat"); async function main() { const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage"); const simpleStorage = await SimpleStorage.deploy(); await simpleStorage.deployed(); console.log(`合约部署地址:${simpleStorage.address}`); } main().catch((error) => { console.error(error); process.exitCode = 1; });
- 启动本地节点并部署合约:
npx hardhat node # 启动本地Hardhat节点 npx hardhat run scripts/deploy.js --network localhost # 部署合约到本地节点
记录终端输出的合约地址。
3. 前端项目配置
- 创建React/Next.js项目:
# React npx create-react-app frontend # Next.js npx create-next-app@latest frontend
- 安装ethers.js(Hardhat官方推荐的交互库):
cd frontend npm install ethers
- 将Hardhat生成的ABI文件(
artifacts/contracts/SimpleStorage.sol/SimpleStorage.json)复制到前端utils目录,导出ABI字段:
export const contractABI = [/* 粘贴JSON中的abi数组 */];
4. 前端合约交互示例
在React组件/Next.js页面中实现钱包连接与合约调用:
import { useState, useEffect } from 'react'; import { ethers } from 'ethers'; import { contractABI } from '../utils/contractABI'; const CONTRACT_ADDRESS = "你的合约部署地址"; function App() { const [contract, setContract] = useState(null); const [value, setValue] = useState(''); useEffect(() => { if (!window.ethereum) { alert("请安装MetaMask钱包"); return; } const init = async () => { const provider = new ethers.providers.Web3Provider(window.ethereum); await provider.send("eth_requestAccounts", []); const signer = provider.getSigner(); const contract = new ethers.Contract(CONTRACT_ADDRESS, contractABI, signer); setContract(contract); // 读取合约初始值 const currentValue = await contract.retrieve(); setValue(currentValue.toString()); }; init(); }, []); const updateValue = async (e) => { e.preventDefault(); if (!contract) return; const tx = await contract.store(value); await tx.wait(); const newVal = await contract.retrieve(); setValue(newVal.toString()); }; return ( <div> <h1>Simple Storage 交互</h1> <p>当前值:{value}</p> <form onSubmit={updateValue}> <input type="text" value={value} onChange={(e) => setValue(e.target.value)} placeholder="输入新值" /> <button type="submit">更新值</button> </form> </div> ); } export default App;
二、Truffle + React/Next.js 配置方案
1. 初始化Truffle项目
npx truffle init npm install
2. 合约编译与部署
- 编写合约(示例:
contracts/SimpleStorage.sol),执行编译:
truffle compile
编译完成后,build/contracts目录会生成包含ABI和字节码的JSON文件。
- 编写迁移脚本(
migrations/2_deploy_contracts.js):
const SimpleStorage = artifacts.require("SimpleStorage"); module.exports = function (deployer) { deployer.deploy(SimpleStorage); };
- 启动Ganache本地节点,执行部署:
truffle migrate --network development
记录终端输出的合约地址。
3. 前端项目配置
- 创建React/Next.js项目(步骤同Hardhat),安装web3.js:
cd frontend npm install web3
- 将Truffle生成的
SimpleStorage.json复制到前端utils目录。
4. 前端合约交互示例
在React组件/Next.js页面中实现交互:
import { useState, useEffect } from 'react'; import Web3 from 'web3'; import SimpleStorage from '../utils/SimpleStorage.json'; const CONTRACT_ADDRESS = "你的合约部署地址"; function App() { const [contract, setContract] = useState(null); const [value, setValue] = useState(''); useEffect(() => { if (!window.ethereum) { alert("请安装MetaMask钱包"); return; } const init = async () => { const web3 = new Web3(window.ethereum); await window.ethereum.enable(); const contract = new web3.eth.Contract(SimpleStorage.abi, CONTRACT_ADDRESS); setContract(contract); // 读取合约初始值 const currentValue = await contract.methods.retrieve().call(); setValue(currentValue); }; init(); }, []); const updateValue = async (e) => { e.preventDefault(); if (!contract) return; const accounts = await web3.eth.getAccounts(); await contract.methods.store(value).send({ from: accounts[0] }); const newVal = await contract.methods.retrieve().call(); setValue(newVal); }; return ( <div> <h1>Simple Storage 交互</h1> <p>当前值:{value}</p> <form onSubmit={updateValue}> <input type="text" value={value} onChange={(e) => setValue(e.target.value)} placeholder="输入新值" /> <button type="submit">更新值</button> </form> </div> ); } export default App;
最佳实践
- 将合约地址存入前端
.env文件,Next.js需使用NEXT_PUBLIC_前缀暴露变量:NEXT_PUBLIC_CONTRACT_ADDRESS=0x... - 本地开发时,确保Hardhat/Ganache节点与前端使用同一网络(默认localhost:8545)。
- 处理钱包连接失败、合约调用异常等边界情况,提升用户体验。
内容的提问来源于stack exchange,提问作者Syed Hadi
相关产品推荐
相关产品推荐

