useDApp: "TypeError: Unsupported chain" calling useContractFunction

Hi Team

Great framework. Can’t seem to get past this one, no matter how I try. Fairly new to dApp design, but pretty sure I have everything setup right.

As soon as I call this,

const { state: buyTx, send: buyTest } = useContractFunction(contract, 'test', { transactionName: 'Buy test' });
buyTest();

I receive this via the:

useEffect(() => {
    console.log(buyTx);
  }, [buyTx]);

image You can clearly see the chainId=5 in the screenshot, this is Goerli and I can connect to my wallet OK to get this far.

I should also state, if I change my contract function to buy1 for example,. it crashes stating Unhandled Rejection (TypeError): contractWithSigner[functionName] is not a function so I know it’s communicating to the very simple buy method I have settup in Solidity (currently returning 123 as a uint256).

Thanks in advance

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (3 by maintainers)

Most upvoted comments

Hey Alex, thanks a lot for your workaround !

It wasn’t working at first on my end because the contract instance wasn’t connect to a signer, had to make some tweaks (also removed chainId as parameter and got it directly from useEthers)

import { useCallback, useState } from 'react'
import { usePromiseTransaction } from '@usedapp/core/dist/esm/src/hooks/usePromiseTransaction'
import { Contract } from '@usedapp/core/node_modules/ethers';
import { Web3Provider } from '@usedapp/core/node_modules/@ethersproject/providers';
import { TransactionOptions, useEthers } from '@usedapp/core';
import { Signer } from 'ethers';

export function connectContractToSigner(contract: Contract, options?: TransactionOptions, library?: Web3Provider) {
  if (contract.signer) {
    return contract
  }

  if (options?.signer) {
    return contract.connect(options.signer as Signer)
  }

  if (library?.getSigner()) {
    return contract.connect(library.getSigner())
  }

  throw new TypeError('No signer available in contract, options or library')
}

export const useContractFunction__fix = (
  contract: Contract,
  functionName: string,
  options?: TransactionOptions
) => {
  const { library, chainId } = useEthers()
  const [events, setEvents] = useState<Record<string, any> | undefined>(
    undefined
  )

  const { promiseTransaction, state } = usePromiseTransaction(chainId, options)

  const send = useCallback(
    async (...args: any[]) => {
      const contractWithSigner = connectContractToSigner(contract, options, library)
      const sendPromise = contractWithSigner[functionName](...args).then(
        (result: any): Promise<any> => {
          // Need to add chainId here to prevent "TypeError: Unsupported Chain" error message
          result.chainId = chainId
          return result
        }
      )

      const receipt: any = await promiseTransaction(sendPromise)

      if (receipt) {
        if (receipt.logs && receipt.logs.length > 0) {
          setEvents(receipt.logs.map((log) => contract.interface.parseLog(log)))
        } else {
          setEvents([])
        }
      }
    },
    [contract, functionName, chainId, promiseTransaction, library, options]
  )

  return { send, state, events }
}

I’ve been having the same issue since yesterday as well. Here’s a workaround that seems to fix the issue. Basically, all we need to do is add the chainId to the result of the contract function.

import { useCallback, useState } from 'react'
import { usePromiseTransaction } from '@usedapp/core/dist/esm/src/hooks/usePromiseTransaction'
import { Contract } from '@ethersproject/contracts'

export const useContractFunction = (
  contract: Contract,
  functionName: string,
  chainId: number | undefined,
  options?: { transactionName?: string }
) => {
  const [events, setEvents] = useState<Record<string, any> | undefined>(
    undefined
  )

  const { promiseTransaction, state } = usePromiseTransaction(chainId, options)

  const send = useCallback(
    async (...args: any[]) => {
      const sendPromise = contract[functionName](...args).then(
        (result: any): Promise<any> => {
          // Need to add chainId here to prevent "TypeError: Unsupported Chain" error message
          result.chainId = chainId
          return result
        }
      )

      const receipt = await promiseTransaction(sendPromise)

      if (receipt) {
        if (receipt.logs && receipt.logs.length > 0) {
          setEvents(receipt.logs.map((log) => contract.interface.parseLog(log)))
        } else {
          setEvents([])
        }
      }
    },
    [contract, functionName, options]
  )

  return { send, state, events }
}

Hi, i fixed the issue with chainId being equal 0, it’s up in version 0.4.5

Also if anyone needs useSendTransaction

import { TransactionRequest } from '@ethersproject/abstract-provider'
import { TransactionOptions, useEthers } from '@usedapp/core';
import { usePromiseTransaction } from '@usedapp/core/dist/esm/src/hooks/usePromiseTransaction';

export function useSendTransaction__fix(options?: TransactionOptions) {
  const { library, chainId } = useEthers()
  const { promiseTransaction, state } = usePromiseTransaction(chainId, options)

  const sendTransaction = async (transactionRequest: TransactionRequest) => {
    const signer = options?.signer || library?.getSigner()
    if (signer) {
      await promiseTransaction(
        signer.sendTransaction(transactionRequest)
          .then(
            (tx: any) => {
              tx.chainId = chainId
              return tx;
            }
          )
      )
    }
  }

  return { sendTransaction, state }
}

Just got this same error on Ropsten. In my case, it likely has to due with Metamask using EIP-1559 type transactions. Yesterday, it was using Legacy type transactions and working fine.