尝试调用合同方法时出现 Web3 错误

Web3 error when trying to call contract methods

我在尝试 运行 使用 React、Truffle 和 Ganache 制作的 dapp 时遇到以下错误。我也在使用 web3 版本 1.7.1。问题是代码进入 try/catch 的 catch(error) 序列,然后正确显示它的意图。为什么会出现这种情况,为什么会出现以下错误?

index.js:1 TypeError: Cannot read properties of undefined (reading 'methods')
at HomePage.componentDidMount

代码应该做什么:显示类似“地址是:0x0D05b3220E9cC7A90623fc506cEB64Ab885FD6C6”的内容

代码的作用:它向我显示提示“无法加载 web3、帐户或合同。检查控制台了解详细信息”然后“地址是:0x0D05b3220E9cC7A90623fc506cEB64Ab885FD6C6”

代码如下:

import React, { Component } from "react";
import MySmartContract from "../contracts/MySmartContract.json";
import getWeb3 from "../getWeb3";

//Importing components



class HomePage extends Component {
  constructor(props) {
    super(props);

    this.state = {
      ContractInstance: undefined,
      account: null,
      web3: null,
      isOwner: false
    }
  }

  componentDidMount = async () => {

    // For refreshing the page a single time
    // so that web3 and instance is loaded every time
    if (!window.location.hash) {
      window.location = window.location + '#loaded';
      window.location.reload();
    }

    try {
      // Get network provider and web3 instance.
      const web3 = await getWeb3();

      // Use web3 to get the user's accounts.
      const accounts = await web3.eth.getAccounts();

      // Get the contract instance.
      const networkId = await web3.eth.net.getId();
      const deployedNetwork = MySmartContract.networks[networkId];
      const instance = new web3.eth.Contract(
        MySmartContract.abi,
        deployedNetwork && deployedNetwork.address,
      );

      // Set web3, accounts, and contract to the state, and then proceed with an
      // example of interacting with the contract's methods.
      this.setState({ ContractInstance: instance, web3: web3, account: accounts[0] });


      const owner = await this.state.ContractInstance.methods.getOwnerAddress().call();
      if (this.state.account === owner) {
        this.setState({ isOwner: true });
      }

  

    } catch (error) {
      // Catch any errors for any of the above operations.
      alert(
        `Failed to load web3, accounts, or contract. Check console for details.`,
      );
      console.error(error);
    }
  };


  render() {


    if (!this.state.web3) {

      return (
       
            <h1>
              Loading Web3, accounts and contract...
            </h1>
          
         
     
      )

    }
    return (
      <div><h1>Address is: {this.state.account}</h1></div>

    )

  }
}

export default HomePage;

getWeb3.js内容如下:

从“web3”导入 Web3;

const getWeb3 = () =>
  new Promise((resolve, reject) => {
    // Wait for loading completion to avoid race conditions with web3 injection timing.
    window.addEventListener("load", async () => {
      // Modern dapp browsers...
      if (window.ethereum) {
        const web3 = new Web3(window.ethereum);
        try {
          // Request account access if needed
          await window.ethereum.enable();
          // Accounts now exposed
          resolve(web3);
        } catch (error) {
          reject(error);
        }
      }
      // Legacy dapp browsers...
      else if (window.web3) {
        // Use Mist/MetaMask's provider.
        const web3 = window.web3;
        console.log("Injected web3 detected.");
        resolve(web3);
      }
      // Fallback to localhost; use dev console port by default...
      else {
        const provider = new Web3.providers.HttpProvider(
          "http://127.0.0.1:8545"
        );
        const web3 = new Web3(provider);
        console.log("No web3 instance injected, using Local web3.");
        resolve(web3);
      }
    });
  });

export default getWeb3;

这段代码好像有误!

this.setState({ ContractInstance: instance, web3: web3, account: accounts[0] });


const owner = await this.state.ContractInstance.methods.getOwnerAddress().call();
      

您不应在设置后立即尝试使用状态值。

所以你需要像这样在第二行调用你的函数:

const owner = await instance.methods.getOwnerAddress().call();

注入的连接器代码示例

const ConnectToInjected = async () => {
  let provider = null;
  if (typeof window.ethereum !== 'undefined') {
    provider = window.ethereum;
    try {
      await provider.request({ method: 'eth_requestAccounts' })
    } catch (error) {
      throw new Error("User Rejected");
    }
  } else if (window.web3) {
    provider = window.web3.currentProvider;
  } else if (window.celo) {
    provider = window.celo;
  } else {
    throw new Error("No Web3 Provider found");
  }
  return provider;
};

export default ConnectToInjected;

用法:

const provider = await ConnectToInjected();
// Open metamask
await provider.request({ method: 'eth_requestAccounts' });
const web3 = new Web3(provider)