简体   繁体   English

在 React 中使用 ABI 和 Ether.js 查询智能合约

[英]Querying Smart Contract using its ABI and Ether.js in React

I have a contract deployed to mai.net.我有一个部署到 mai.net 的合同。 I have a javascript file which exports the functions so they could be called by other files.我有一个 javascript 文件,它导出函数以便其他文件可以调用它们。 I have a button that calls getOwnerOfToken from my react.我有一个从我的反应中调用getOwnerOfToken的按钮。 When I click on the button nothing happens and nothing is logged.当我点击按钮时,没有任何反应,也没有任何记录。 I understand that since this is a view read-only method I only need the provider (metamask).我知道因为这是一个视图只读方法,所以我只需要提供者(metamask)。 Before accessing the application I validate the user so metamask is detected using window.ethereum .在访问应用程序之前,我验证了用户,以便使用window.ethereum检测到元掩码。

// Gallery.js (a react component)
import React from "react";
import { getOwnerOfToken } from "../services/nftcontract";

class Gallery extends React.Component {
  constructor(props){
     //constructor stuff here
  }


  // called by onClick of a button in react
  handleProfileChange = selected(selectedIndex) => {
      getOwnerOfToken(selectedIndex).then((address) => {
      this.setState({ currentSelectionnOwner: address });
      console.log(this.state.currentSelectionnOwner);
     });
   }

  render() { 
      // a button with the callback attached to onclick
      <button onClick=onClick={() => this.handleProfileChange ()}>Change Profile</button>
  }
}

Here is the service/nftcontract.js file that was imported above这是上面导入的 service/nftcontract.js 文件

import { ethers } from "ethers";

// Note: the full abi was copied from the ABI section found in etherscan. 
// This is a simplified version for this example
const abi = [
  {
    inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }],
    name: "ownerOf",
    outputs: [{ internalType: "address", name: "", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
];

const provider = new ethers.providers.Web3Provider(window.ethereum);
const address = global.config.addresses.collections.genesis;
const contract = new ethers.Contract(address, abi, provider);

const getOwnerOfToken = async (tokenid) => {
  return await contract.ownerOf(tokenid);
};

export { getOwnerOfToken };

EDIT with Solution: I found the problem.编辑解决方案:我发现了问题。 It was a metamask injection issue.这是一个元掩码注入问题。 On startup an async call would occur before metamask could inject into the window. This did not happen all the time in my case but it would occur when first visiting the app.在启动时,在 metamask 可以注入 window 之前会发生异步调用。在我的情况下,这并非一直发生,但会在首次访问应用程序时发生。 So to solve that issue I moved all the variables inside the async function like so.所以为了解决这个问题,我像这样移动了异步 function 中的所有变量。 So whenever an async call is made a new contract instance is created.因此,每当进行异步调用时,都会创建一个新的合约实例。

const getOwnerOfToken = async (tokenid) => {
  const provider = new ethers.providers.Web3Provider(window.ethereum);
  const address = global.config.addresses.collections.genesis; 
  const contract = new ethers.Contract(address, abi, provider);
  const ownerAddress = await contract.ownerOf(tokenid);
  //   console.log(`EFService: ${ownerAddress}`);
  return ownerAddress;
};

You are supposed to call the getSigner() on the provider like this您应该像这样在provider上调用getSigner()

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const address = global.config.addresses.collections.genesis;
const contract = new ethers.Contract(address, abi, signer);

getSigner() from official docs来自官方文档的getSigner()

Returns a JsonRpcSigner which is managed by this Ethereum node, at addressOrIndex.返回由此以太坊节点管理的 JsonRpcSigner,地址为 addressOrIndex。 If no addressOrIndex is provided, the first account (account #0) is used.如果未提供 addressOrIndex,则使用第一个帐户(帐户 #0)。

You can read it here https://docs.ethers.io/v5/api/providers/jsonrpc-provider/你可以在这里阅读它https://docs.ethers.io/v5/api/providers/jsonrpc-provider/

Also, make sure you are passing the correct address in the ethers.contract另外,请确保您在ethers.contract中传递了正确的地址

ps: You should switch from classes to functional components in react ps:你应该在反应中从类切换到功能组件

暂无
暂无

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

相关问题 如何在智能合约中将地址连接到午餐 function? | TypeError:无法读取未定义的属性(读取“连接”)ether.js - how can i connect an address to lunch a function in the smart contract ? | TypeError: Cannot read properties of undefined (reading 'connect') ether.js 在使用 ether.js 时调用还原异常 - call revert exception in using ether.js 如何从 React 前端向智能合约发送可变数量的以太币? - How to send variable amount of ether to smart contract from React front end? 如何调用 Solidity 函数从智能合约返回 Ether? - How to call Solidity Function to return Ether from Smart Contract? Metamask 交易预计会在智能合约 function 上失败,该合约会批量进行以太币转账 - Metamask transaction is expected to fail on a Smart Contract function that batches ether transfer 使用 react.js 努力在 web 页面中显示智能合约信息 - Struggling to display Smart Contract information in web page using react.js 使用智能合约中的项目更新 React JS 中的 state 数组 - Update state array in React JS with item from Smart Contract 如何从 React JS 访问智能合约功能? - How to access smart contract functions from React JS? 无法使用 web3.js 从智能合约调用 function - Unable to call function from smart contract using web3.js 如何用WalletConnect调用智能合约function? (React.js, Node.js) - How to call a smart contract function with WalletConnect? (React.js, Node.js)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM