[SOLVED] ParseServer + Moralis v2 + React-Moralis + NextJs

Love moralis products but the confusion is real for me. At the moment this is my setup.

  • NextJS app
  • Parse self hosted Server

I have authentication setup and running smoothly. The issue I am having is I am using react-moralis and I cannot get the useApiContract hook to work for runContractFunction.

After reading similar help threads about this topic on here and trying to debug my issue I have some more information to add:

Using swaggerUI I was able to get a successful runContractFunction call to my contract so I know the ABI format, chainID, contract address, etc, etc, are all correct on my front.

Meanwhile in my NextJS app I keep getting this response message from the parseServer in regards to the runContractFunction hook:
{“code”:141,“error”:"{“message”:“Cannot read properties of undefined (reading ‘inputs’), Function undefined not found in ABI, function_name should not be empty”}"}

So my question is as follows. If you are self-hosting your own parse server do you have to use EvmAPI now in my react client instead of react-moralis? It seems react-moralis does not work with a self-hosted server. I spent over an hour trying to get a simple totalSupply view function call from react-moralis which in the past worked the first time I wrote the code.

Am I to assume if you self-host your own moralis server that react-moralis is not going to work?

The React demo from the self hosted tutorial uses react-moralis and an API hook so it should work. What is the exact code that you’re using?

1 Like

Hey this is the code:

const { runContractFunction, data } =

    useApiContract({

      address: StupidContract,

      functionName: "totalSupply",

      abi: [{inputs: [], name: "totalSupply", outputs: [{internalType: "uint256", name: "",  type: "uint256"}], stateMutability: "view",  type: "function"}],

      chain: "0x5",

      params: { },

    });

using swaggerUI it works but not by using react-moralis. I did check that tutorial video but the example is using a different hook that doesnt involve abi or contract functions. The example was using a getNFTs hook from react-moralis which I’m assuming isdifferent from calling a contract’s functions?

When using react-moralis, is the self-hosted server the one that is supposed to handle the requests?

For instance is this correct to get called from the client: https://moralis-host3473.herokuapp.com/server/functions/runContractFunction

on my heroku server it says this in the logs:

2022-10-15T04:06:19.364798+00:00 app[web.1]: Moralis[evmApi]: native.runContractFunction() is depreciated and will be removed soon. Please use utils.runContractFunction()
2022-10-15T04:06:19.420258+00:00 app[web.1]: error: Failed running cloud function runContractFunction for user ElWqrMbUII with:
2022-10-15T04:06:19.420260+00:00 app[web.1]:   Input: {"abi":[{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"chain":"0x5","function_name":"totalSupply","address":"0xCe5DaEEaA54fed474a74C0E3570D64FDf4bA4cE7","params":{}}

2022-10-15T04:06:19.420271+00:00 app[web.1]: Error: {"message":"{\"message\":\"Cannot read properties of undefined (reading 'inputs'), Function `undefined` not found in ABI, function_name should not be empty\"}","code":141} {"error":{"code":141,"message":"{\"message\":\"Cannot read properties of undefined (reading 'inputs'), Function `undefined` not found in ABI, function_name should not be empty\"}"},"functionName":"runContractFunction","params":{"abi":[{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"address":"0xCe5DaEEaA54fed474a74C0E3570D64FDf4bA4cE7","chain":"0x5","function_name":"totalSupply","params":{}},"user":"ElWqrMbUII"}

I had similar errors when I tried. I had to make this change in the Parse server cloud function code before it worked.

Build: /src/cloud/generated/evmApi.ts (then npm run build and npm run start)

Parse.Cloud.define('runContractFunction', async ({ params, user, ip }: any) => {
    
    ...
 
    const result = await Moralis.EvmApi.native.runContractFunction({
      ...params,
      functionName: params.function_name,
    });
1 Like

I’m unclear what to change. Is this code here the updated version or the old version?

My code doesnt look like that btw. /src/cloud/generated/evmApi.ts file looks like this:

Parse.Cloud.define("runContractFunction", async ({params, user, ip}: any) => {

  try {

    await beforeApiRequest(user, ip, 'runContractFunction');

    const result = await Moralis.EvmApi.native.runContractFunction(params);

    return result?.raw;

  } catch (error) {

    throw new Error(getErrorMessage(error, 'runContractFunction'));

  }

})

My build/cloud/generated/evmApi.js file looks like this:

Parse.Cloud.define("runContractFunction", async ({ params, user, ip }) => {

    try {

        await beforeApiRequest(user, ip, 'runContractFunction');

        const result = await moralis_1.default.EvmApi.native.runContractFunction(params);

        return result === null || result === void 0 ? void 0 : result.raw;

    }

    catch (error) {

        throw new Error(getErrorMessage(error, 'runContractFunction'));

    }

});

Btw U updated my moralis version from 2.2 to 2.65. Not sure if that matters or not. Still gives me same error after upgrading.

I edited the build example, forgot to change the object name.

The two snippets are from different files - the first is for where the build comes from, the second is the build that is served (npm run start).

The moralis version I used is the default 2.2.0.

const result = await Moralis.EvmApi.native.runContractFunction(params);

This is the original - see the difference between the use of the object that is passed into runContractFunction.

1 Like

Thanks you’re right it works!

For anyone else you need to pass the params for functionName:

const result = await Moralis.EvmApi.native.runContractFunction({
      ...params,
      functionName: params.function_name,
    });

Then you run yarn build and then push to heroku or whatever host you are using.