web3-react
web3-react copied to clipboard
How to properly handle Signer or Provider when using ethers Contract in v8?
I have an app wrapped in <Web3ReactProvider>:
// App.js
import ethers from 'ethers';
import { useEffect } from 'react';
import { Web3ReactProvider } from '@web3-react/core';
import { hooks, metaMask } from '../connectors/MetaMask';
import Home from './Home';
const connectors = [[metaMask, hooks]];
const getLibrary = provider => new ethers.providers.Web3Provider(provider);
const App = () => {
useEffect(() => {
void metaMask.activate(43114);
}, []);
return (
<Web3ReactProvider connectors={connectors} getLibrary={getLibrary}>
<Home />
</Web3ReactProvider>
);
}
export default App;
And I'm trying to read a contract like this:
// Home.js
import { useWeb3React } from '@web3-react/core';
import { useEffect, useMemo } from 'react';
import { Contract } from 'ethers';
const Home = () => {
const { provider } = useWeb3React();
const address = '...';
const abi = '...'
const signerOrProvider = useMemo(() => {
if (provider?.['getSigner']) {
return provider.getSigner();
} else {
return provider;
}
}, [provider]);
useEffect(() => {
try {
const contract = new Contract(address, abi, signerOrProvider);
console.log(contract);
} catch (e) {
console.error(e)
}
}, [abi, address, signerOrProvider]);
return (
<div>
...
</div>
)
}
export default Home;
The error I'm getting:
Error: invalid signer or provider (arg="signerOrProvider", value="[object Object]", version=4.0.49)
at Object.n [as throwError] (ethers.min.js:1:1)
at new A (ethers.min.js:1:1)
at Wallet.js:25:1
at commitHookEffectListMount (react-dom.development.js:22969:1)
at commitPassiveMountOnFiber (react-dom.development.js:24702:1)
at commitPassiveMountEffects_complete (react-dom.development.js:24666:1)
at commitPassiveMountEffects_begin (react-dom.development.js:24653:1)
at commitPassiveMountEffects (react-dom.development.js:24641:1)
at flushPassiveEffectsImpl (react-dom.development.js:26848:1)
at flushPassiveEffects (react-dom.development.js:26801:1)
at commitRootImpl (react-dom.development.js:26752:1)
at commitRoot (react-dom.development.js:26517:1)
at performSyncWorkOnRoot (react-dom.development.js:25956:1)
at flushSyncCallbacks (react-dom.development.js:11982:1)
at react-dom.development.js:25490:1
How exactly can I read a contract if I use web3 versions "@web3-react/core": "^8.0.23-beta.0" and "@web3-react/metamask": "^8.0.19-beta.0"? Thanks!
Can't really tell what exactly is going wrong. However, this is how I've been handling it:
function useContract(contract) {
const connector = usePriorityConnector();
const provider = usePriorityProvider();
contract = contract.connect(provider);
if (getConnectorName(connector) !== "Network") {
const signer = provider?.getSigner?.();
if (signer !== undefined) contract = contract.connect(signer);
}
return contract;
}
Then you would simply call it like this:
const address = '...';
const abi = '...'
const myContract = new Contract(address, abi);
const Home = () => {
const contract = useContract(myContract);
...
}
Hey could you please help with a full example in js? I can't seem to make it work, I couldn't figure out how to use usePriorityConnector... Thanks
@0xPhaze Can you please tell how to import usePriorityProvider() or is it a self-written hook?
Almost all my projects use this
async function getLibrary(provider) {
return new Web3Provider(provider); // From @ethersproject/providers
}
const library = getLibrary(provider)
const claim = async () => {
if (isActive && connector.provider) {
const contract = new Contract(
ADDRESS,
ABI,
await library.getSigner()
);
}
};