[英]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.