I'm trying to call the name
function of my smart contract through my React application, but I'm getting the error: Error: contract runner does not support calling
useSigner
hook:
import { ethers } from "ethers";
import { useEffect, useState } from "react";
import { ISigner } from "@/src/interfaces";
import { useError } from "./useError";
import { parseRPCError } from "../utils";
export const useSigner = (provider: ethers.JsonRpcProvider) => {
const [value, setValue] = useState<ISigner>({
account: undefined,
balance: undefined,
network: undefined,
});
const { error, setError } = useError();
useEffect(() => {
(async () => {
if (!provider) return;
else await requestAccount();
})();
}, [provider]);
const getSignerFromProvider = async () => await provider.getSigner();
const setSigner = (signer: ISigner) => setValue(signer);
const requestAccount = async () => {
try {
const signer = await getSignerFromProvider();
const balance = await provider.getBalance(signer.address);
const network = await provider.getNetwork();
setSigner({
account: signer,
balance: balance.toString(),
network: network.chainId.toString(),
});
} catch (err: any) {
const parsedError = parseRPCError(err);
setError(parsedError);
}
};
return { signer: value, setSigner, error, setError };
};
The page where I'm calling the hook:
"use client";
import { FC, useEffect, useState } from "react";
import NFTContractABI from "@/src/abi/NFT.json";
import contractsAddresses from "@/src/contracts.json";
import { ethers } from "ethers";
import { IWrapped } from "@/src/interfaces";
import { withProvider } from "@/src/hoc";
import { useSigner } from "@/src/hooks/useSigner";
const MintNFTPage: FC<IWrapped> = ({ provider }) => {
const [contracts, setContracts] = useState<any>({});
const { signer, setSigner } = useSigner(provider);
useEffect(() => {
const contract = new ethers.Contract(
contractsAddresses.nft,
NFTContractABI.abi,
signer.account
);
contract.setContracts({ ...contracts, nft: contract });
}, []);
const mintNFT = async () => {
console.log("Starting NFT minting");
console.log(contracts.nft);
};
return <button onClick={mintNFT}>Click here to mint a NFT</button>;
};
export default withProvider(MintNFTPage);
And here is where I get the provider:
"use client";
import { useState, useEffect, FC } from "react";
import { ethers } from "ethers";
import { Alchemy, Network } from "alchemy-sdk";
import { IWrapped } from "../interfaces";
export const withProvider = (WrappedComponent: FC<IWrapped>) => {
const EnhancedComponent: FC = (props) => {
const [provider, setProvider] = useState<ethers.JsonRpcProvider>();
const [alchemy, setAlchemy] = useState<Alchemy>();
function createAlchemy() {
const config = {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_GOERLI,
};
const alchemy = new Alchemy(config);
return alchemy;
}
useEffect(() => {
if (!window.ethereum) {
alert("Metamask is not installed!");
return;
}
const alch = createAlchemy();
const prov = new ethers.JsonRpcProvider("http://localhost:8545");
setProvider(prov);
setAlchemy(alch);
}, []);
return (
<WrappedComponent {...props} provider={provider!} alchemy={alchemy!} />
);
};
return EnhancedComponent;
};
I thought that by passing the signer instead of the provider when initializing an instance of a ethers.Contract
would work, but I guess it's not. How can I do it properly?