Web3 Provider未设置或无效,Next.js连接Rinkeby链合约报错问题问询
报错原因
- 核心问题是你在
herbie.ts中初始化Web3实例时没有关联任何节点provider:你直接调用了new Web3()创建空白实例,这个实例不知道要连接Rinkeby的Infura节点,所以基于它生成的合约实例发起链上调用时找不到可用的连接通道,就抛出了provider缺失的报错。 - 其次你已经通过
useWeb3hook拿到了已经配置好Infura节点的web3实例(就是返回值里的lib字段),但是你没有把这个实例传给合约创建逻辑用,两个逻辑完全割裂。
修复方案
首先修改./src/lib/herbie.ts,调整createContract方法接收外部传入的已配置好provider的Web3实例:
import Web3 from "web3"; const getAbi = async (): Promise<any> => { const abi = await (await fetch("/abi.json")).json(); return abi; }; // 新增参数接收外部传入的Web3实例 const createContract = async (web3: Web3): Promise<any> => { return new web3.eth.Contract( await getAbi(), "0xe71c56d861f90bf96c9f006d25ce91da97ddb238" ); }; export { getAbi, createContract };
然后修改./src/pages/index.tsx,把useWeb3返回的lib实例传入createContract,同时补全异步方法的await关键字:
import type { NextPage } from "next"; import React, { useEffect, useState } from "react"; import { useWeb3 } from "@openzeppelin/network/react"; import { createContract } from "../lib/herbie"; const Index: NextPage<IndexProps> = () => { const { networkId, networkName, providerName, accounts, lib } = useWeb3( `wss://rinkeby.infura.io/ws/v3/${process.env.INFURA_PROJECT_ID}` ); useEffect(() => { const fetchContract = async (): Promise<any> => { if (networkId === 4 && accounts.length > 0 && lib) { // 传入已经配置好provider的web3实例 const contract = await createContract(lib); console.log({ contract }); // 补全await获取异步调用结果 const balance = await contract.methods.balanceOf(accounts[0]).call(); console.log("账户余额:", balance); } }; fetchContract(); }, [accounts, networkId, lib]); return ( <div> <p> {JSON.stringify({ networkId, networkName, providerName, accounts, })} </p> </div> ); }; export default Index;
补充说明:你原有代码中调用
call()时没有加await,call()是异步方法,不加的话只能拿到Promise对象而非实际的余额结果,修复时需要注意。
内容的提问来源于stack exchange,提问作者Herbie Vine
相关产品推荐
相关产品推荐

