chanId is always null - no way to get the chain a user used to authenticate

After upgrading to moralis 1.2.3 and react-moralis 1.2.1, there is no way to get the id of the chain a user used to authenticate.

const { authenticate, chainId } = useMoralis();

The chainId always stays null even after the user authenticates with MetaMask.

For example, when a user uses MetaMask on Polygon on Binance to authenticate, in the onSuccess event handler the chainId is still null and under user.attributes there is no property to indicate which chain the user used.
All I can see on the user attributes object is authData.moralisEth object and an ethAddress property (even when the user used a different chain to authenticate.

I tried to get the chain id in vanilla js:

web3 = await Moralis.enableWeb3()
x = await web3.detectNetwork()

we’ll have to fix it in the SDK, thanks for reporting

1 Like

Thanks! That works. Just tested with multiple chains.

What does your code looks like? Tested it with the latest version and seems to work correctly:


const { authenticate, chainId, authError } = useMoralis();

return (
  <div>
    <button onClick={() => authenticate({throwOnError: true})}>Authenticate</button>
    <p>ChainId: {chainId}</p>
    <p>Error: {authError?.message ?? "-"}</p>
  </div>
)

Additionally, after authenticate is completed, what does Moralis.chainId return for you?

const { authenticate, Moralis, chainId } = useMoralis();
const onConnectWithMoralisAndMetaMask = async () => {
    // If the user is adding his first wallet?
    if (wallets.length === 0) {
      authenticate({
        signingMessage: "Connect wallet with Gallerium",
        onSuccess: onMoralisConnectSuccess,
        onError: () => {
          onwalletFailedToConnect();
        },
      });
    } else {
      const permissions = await window.ethereum.request({
        method: "wallet_requestPermissions",
        params: [
          {
            eth_accounts: {},
          },
        ],
      });

      if (permissions) {
        authenticate({
          signingMessage: "Connect wallet with Gallerium",
          onSuccess: onMoralisConnectSuccess,
          onError: () => {
            onwalletFailedToConnect();
          },
        });
      }
    }
  };

And:

const onMoralisConnectSuccess = async (user: any) => {    
      const address = user.attributes.accounts[0];
      const chain = chainId!;
      onWalletConnected(address, chain);
  };

The above code with the permissions was the only way we found in the past to allow users to switch network/account in MetaMask and connect with another wallet. Maybe there is simpler way of doing it now, but in previous versions this was the only solution that worked.

the chainId (And other values from react-moralis hook), might not be set at the moment when you call onSuccess. This is because these values are set after onWeb3Enabled event has been fired.

What you can do is making an useEffect hook and check when the chainId / user are set, and then call your function.

const {user, chainId} = useMoralis()
useEffect(()=>{
  if(chainId && user) {
    const address = user.attributes.accounts[0];
    onWalletConnected(address, chain)
  }
}, [chainId, user])

Or You might want to listen for the web3Enabled event. Something along the lines of:

useEffect(() => {
  const unsub = Moralis.onWeb3Enabled((args) => console.log("Your logic", args));
  return () => {
    unsub()
  }
}, [Moralis]);

Hmmm… in our product we allow the user to connect multiple wallets. So the code above will actually be called when the page just loads as he already has a wallet connected.
We can probably figure something out around it (checking the state to see if this wallet already exists, etc).
But honestly - it would be so much simpler if you would pass the chain ID to the success event handler. I mean - this is information that you probably already have from ethers.js/web3.js that you are using under the hood to connect to the wallet.

Thanks for following up!

Have the chainId from sdk been fixed?

I have just upgraded to the latest version of:

"moralis": "^1.6.0",
"react-moralis": "^1.3.5",

and trying the get chainId by

const { chainId } = useMoralis()

sometimes I get it and sometimes it returns null. :smiley:

I have it in a simple custom hook.

1 Like

how do you use it? my expectation is that that the chain id will be set after web3 is enabled

Hey @cryptokid,

thanks for quick reply. :slight_smile:

I use it like this.

import { useEffect, useState } from 'react'
import { useWeb3React } from '@web3-react/core'
import { useMoralis } from 'react-moralis'

export const useGetNftAssetsData = (collectionId: string) => {
  const [data, setData] = useState(null)
  const [isLoading, setIsLoading] = useState(true)
  const [fetchError, setFetchError] = useState(false)

  const { account } = useWeb3React()
  const { Moralis, chainId } = useMoralis()
...

Is there an extra initialization for web3? I thought that after version 1.0 you no longer use web3 but ethers. :thinking:

When he says web3 he just means web3provider (not the library web3.js) which is ethers.js. chainId should be updated with a valid value when a wallet has been connected.

You need to be using chainId at some stage (not talking about declaring it from useMoralis) after a web3 connection has been made.

Hey @glad,

thanks for the message.

When he says web3 he just means web3provider (not the library web3.js) which is ethers.js.

Understood. :slight_smile:

chainId should be updated with a valid value when a wallet has been connected.

When I connect the wallet this

const { account } = useWeb3React()

returns correctly a wallet and returns correctly a chainId. I can do

const { account, chainId } = useWeb3React()

to get chainId: Number from useWeb3React().

What was working before the updating the libs was

const { Moralis, chainId } = useMoralis()

Now it is not working on the latest version. chainId: string | null from useMoralis() is null when I connect the wallet.

What am I missing.

Not sure I follow you with

You need to be using chainId at some stage (not talking about declaring it from useMoralis ) after a web3 connection has been made.

I AM talking about declaring it from useMoralis because that is what was working before. :slight_smile:

chainId: string | null from useMoralis() is null

Can we see your wallet connect code or component where you’re using this custom hook? There might be an execution issue where you’re trying to use the chainId before it’s actually available or valid.

Sure. Here it is:

export const useGetNftAssetsData = (collectionId: string) => {
  const [data, setData] = useState(null)
  const [isLoading, setIsLoading] = useState(true)
  const [fetchError, setFetchError] = useState(false)

  const { chainId } = useMoralis()
  const { account } = useWeb3React()
  const Web3Api = useMoralisWeb3Api();

  useEffect(() => {
    const fetchData = async () => {

      try {
        if (collectionId && chainId && account) {
          const options = {
            chain: chainId,
            address: 'addressString',
            token_address: collectionId,
            // limit must be less than 500
            limit: 499
          }
          setIsLoading(true)
          // @ts-ignore
          const response = await Web3Api.account.getNFTsForContract(options)
          setData(response?.result)
          setIsLoading(false)
        }
      } catch (error) {
        console.error('Unable to fetch data:', error)
        setFetchError(true)
        setIsLoading(false)
      }
    }
    fetchData()
  }, [collectionId, chainId, account, setData, setIsLoading, Web3Api.account, Web3Api.token])
  return { data, isLoading, fetchError }
}

I also have an issue with typescript showing the following:

TS2345: Argument of type '{ chain: string; address: string; token_address: string; limit: number; }' is not assignable to parameter of type '{ chain?: "eth" | "0x1" | "ropsten" | "0x3" | "rinkeby" | "0x4" | "goerli" | "0x5" | "kovan" | "0x2a" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | ... 6 more ... | "0xfa"; format?: "decimal" | "hex"; offset?: number; limit?: number; } & { ...; }'. Type '{ chain: string; address: string; token_address: string; limit: number; }' is not assignable to type '{ chain?: "eth" | "0x1" | "ropsten" | "0x3" | "rinkeby" | "0x4" | "goerli" | "0x5" | "kovan" | "0x2a" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | ... 5 more ... | "0xfa"; format?: "decimal" | "hex"; offset?: number; limit?: number; }'. Types of property 'chain' are incompatible. Type 'string' is not assignable to type '"eth" | "0x1" | "ropsten" | "0x3" | "rinkeby" | "0x4" | "goerli" | "0x5" | "kovan" | "0x2a" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | ... 5 more ... | "0xfa"'.

for options variable. Where it complaints about the chain not being compatible.

And also:

const Providers: React.FC = ({ children }) => {
  return (
    <Provider store={store}>
      <Web3ReactProvider getLibrary={getLibrary}>
        <ToastsProvider>
          <HelmetProvider>
            <MoralisProvider appId={MORALIS_APP_ID} serverUrl={MORALIS_SERVER_URL}>
              <ThemeProviderWrapper>
                <LanguageProvider>
                  <RefreshContextProvider>
                    <PancakeModalProvider>
                      <ModalProvider>{children}</ModalProvider>
...

Try enableWeb3 before getting chainId

1 Like

You get const { enableWeb3, isWeb3Enabled } = useMoralis(); and add the litttle fix

useEffect(() => {
  const fetchData = async () => {
    // ...
  };
  // Add the simple check
  if (!isWeb3Enabled) {
    enableWeb3();
  } else {
    fetchData();
  }
}, [
  // ..., 
  isWeb3Enabled, //add isWeb3Enabled to your dependencies
]);
1 Like

Ahaaa. I didn’t know we have to do a check for it. :slight_smile: Thanks for pointing it out and sharing a fix.

Top! Really appreciate. Give me your binance wallet address, I will send you some tip for helping out. :slight_smile:

It’s fine. I’m happy :smiley: this solves your issue rather. Thanks.

1 Like