简体   繁体   English

Web3 - 提供者未设置或无效

[英]Web3 - Provider not set or invalid

I'm trying to connect my frontend (Nextjs) with my contract on the Rinkeby Network ( token on etherscan ).我正在尝试将我的前端(Nextjs)与我在 Rinkeby 网络上的合同(etherscan 上的令牌)连接起来。 I'm new to the crypto space, so I'm not sure what provider it's talking about... I thought the connection was made with the useWeb3 hook, and everything was handled by Infura.我是加密领域的新手,所以我不确定它在说什么提供者......我认为连接是使用 useWeb3 钩子建立的,一切都由 Infura 处理。 I also want to note that I can connect to the Ethereum network with this setup, but not to my token on the Ethereum network.我还想指出,我可以使用此设置连接到以太坊网络,但不能连接到我在以太坊网络上的令牌。

I have this setup on my frontend:我的前端有这个设置:

./src/pages/index.tsx : ./src/pages/index.tsx

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) {
        const contract = await createContract();

        console.log({ contract });

        console.log(contract.methods.balanceOf(accounts[0]).call()); // ERROR HERE
      }
    };

    fetchContract();
  }, [accounts, networkId]);

  return (
    <div>
      <p>
        {JSON.stringify({
          networkId,
          networkName,
          providerName,
          accounts,
        })}
      </p>
    </div>
  );
};

export default Index;

./src/lib/herbie.ts : ./src/lib/herbie.ts

import Web3 from "web3";

const getAbi = async (): Promise<string> => {
  const abi = await (await fetch("/abi.json")).json();

  return abi;
};

const createContract = async (): Promise<any> => {
  const herbieContract = new Web3().eth.Contract;

  return new herbieContract(
    (await getAbi()) as any,
    "0xe71c56d861f90bf96c9f006d25ce91da97ddb238"
  );
};

export { getAbi, createContract };

I get the following error:我收到以下错误:

在此处输入图像描述

My metamask:我的元掩码:

在此处输入图像描述

Thanks谢谢

You need to pass the provider into the contract instance as it says in thedocumentation您需要按照文档中的说明将提供程序传递到合同实例中

const contract = new Web3().eth.Contract(abi, address);
Contract.setProvider(`wss://rinkeby.infura.io/ws/v3/${process.env.INFURA_PROJECT_ID}`);

Almost all production code uses ethersjs instead of web3js btw.几乎所有的生产代码都使用 ethersjs 而不是 web3js 顺便说一句。

It looks like this instead:它看起来像这样:

const contract = new Contract(address, abi, library);

You are getting abi and address to create the contract but to be able to interact with the blockchain, you need a provider.您正在获取 abi 和地址来创建合同,但要能够与区块链交互,您需要一个提供者。 provider is kinda a bridge that connects your contract to the blockchain. provider有点像一座将你的合约连接到区块链的桥梁。

to load the provider you could use @metamask/detect-provider , you can get the provider in one line:要加载可以使用@metamask/detect-provider 的提供程序,您可以在一行中获取提供程序:

import detectEthereumProvider from '@metamask/detect-provider'

const provider = await detectEthereumProvider()

I manually load the provider to show what happens behind the scene:我手动加载提供程序以显示幕后发生的事情:

const [web3Api, setWeb3Api] = useState({
    provider: null,
    web3: null,
    contract:contract
  })


useEffect(() => {
    const loadProvider = async () => {
      // I assume your code to load contract is working
      const contract=  await createContract()
      let provider = null;
      // early metamask injects ethereum
      if (window.ethereum) {
        provider = window.ethereum;
        try {
          await provider.enable();
        } catch {
          console.error("User denied accounts access!")
        }
      }
      // new version metamask injects web3
      else if (window.web3) {
        provider = window.web3.currentProvider
      }
      else if (!process.env.production) {
        // this is ganache provider in development
        provider = new Web3.providers.HttpProvider("http://localhost:7545")
      }
    if (provider) {
        setWeb3Api({
           web3: new Web3(provider),
           provider,
           contract
    })
  } else {
    console.error("Please, install Metamask.")
  }
   }
    loadProvider()
  }, [])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM