2

I have a React (Typescript) app that was booted from Next.js and I want to connect it to the user's wallet. I've noticed 3 ways of doing the same:

  1. With Web3.js
  2. With Ethers.js
  3. With the generic window.ethereum object, which needs to be declared within the consuming script.

I'm using the window.ethereum API (because, why not), but I'm having some problems making the window.ethereum's type available to components, maybe due to the fact that Next overrides React's out-of-the-box configuration. Note that this is happenning despite the fact that I have this type globally declared in types/index.d.ts within my app's root folder:

import { MetaMaskInpageProvider } from "@metamask/providers";

declare global {
  interface Window{
    ethereum?:MetaMaskInpageProvider
  }
}

I am also including the path for this types/ folder in my tsconfig file, like so:

  "include": ["next-env.d.ts", "./types", "**/*.ts", "**/*.tsx"],

Strangely enough, this succeeds in making the window.ethereum object available within a function inside my React component:

const getUserBalance = (address: any) => {
 

   if (window.ethereum) {
        window.ethereum.request({ method: 'eth_getBalance', params: [address, 'latest'] })
            .then(balance => {
                setUserBalance(ethers.utils.formatEther(BigNumber.from(balance)))
            })
    }
}

But inside the same component, as an event declared at the same level, it doesn't recognize the window.ethereum object, saying the 'Object is possibly undefined':

window.ethereum.on('accountsChanged', accountChangedHandler);

I am aware that I can just skip this issue by using the web3.js or ethers.js libraries, but I would like to know, why is this happening? Thank you very much in advance for any help I can get.

2 Answers 2

1

In getUserBalance you have a guard

if (window.ethereum) {
  // code here will run if window.ethereum is defined
  }

But in other case you do not have a guard. So add ?

window.ethereum?.on('accountsChanged', accountChangedHandler)
1

I usually use //@ts-ignore or

declare global {
    interface window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.