Incorrect behavior running execute function

Hi, I have a problem when executing a web3 function that send data to the smart contract.
See this function as setting a price for ERC-1155 collection where the collection has 2 or more different items in it. When I run the function through remix it works fine. But when I call the function is called through my react app using Moralis, the price does not update correctly. Example and code below:
My function in the ABI:

"inputs": [
        {
          "internalType": "uint256[]",
          "name": "_priceList",
          "type": "uint256[]"
        },
        {
          "internalType": "uint256[]",
          "name": "_ids",
          "type": "uint256[]"
        }
      ],
      "name": "setPriceForAll",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
const handleOk = async () => {
        setConfirmLoading(true);
        let ids = [];
        let listPrices = []
        for(let k = 0; k<props.numberOfTiers;k++) {
            if(priceTier[`tier${k}`] !== undefined && priceTier[`tier${k}`] !== null){
                listPrices.push(priceTier[`tier${k}`]);
                ids.push(k);
            }
        }
        console.log(ids, listPrices); // I logged to make sure value match what I expect
        let options = {
            chain: "rinkeby",
            contractAddress: props.contractAddress,
            functionName: "setPriceForAll",
            abi: props.abi,
            params : {
                _priceList : [listPrices],
                _ids : [ids]
            }
        }
        try {
            let tx = await Moralis.executeFunction(options)
            await tx.wait()
            .then(() => {
                console.log(tx); 
            })
        } catch (error) {
            console.log(error.message);
        } finally {
            setConfirmLoading(false);
        }
    }

Let’s say my ids are 0 and 1 and the price associated with them are 50 and 210 respectively. The function will run but the price set for each ID will be different: for ID 0 I will get a price of whatever the value was set to before (by default it’s 0) and for the second I get 210. I am not sure what’s going on here to be honest.

Also if I only update a signle value so let’s say ID 1 I set to price 500, it works correctly.

It works fine really, but try check if you’re passing the correct params. You can try console.log(options) to be sure you’re passing the proper value. And there is no chain in the params, rather make sure you’re connected on the proper network in your case rinkeby before executing the function. And you can also consider looking into writing it in a react way ( optional but better ) https://github.com/MoralisWeb3/react-moralis#useweb3executefunction

so I tried to console log the options I have the correct result, also I have noticed that if I set the _pricelist and _ids with default value and remove them from

for(let k = 0; k<props.numberOfTiers;k++) {
            if(priceTier[`tier${k}`] !== undefined && priceTier[`tier${k}`] !== null){
                listPrices.push(priceTier[`tier${k}`]);
                ids.push(k);
            }
        }

It works fine, the thing I don’t understand if that if I keep the code above and I log the output I get the correct output.
Finally, removing chain and changing to useWeb3executeFunction hook did not fix the problem

Seemed you’re not doing it properly. If the above works fine, you can use that, meanwhile if you don’t mind to share how you’re doing it with useWeb3executeFunction

The above works if I remove the part I put in code quote above but I need this part so it does not work basically. this is what I meant

Are you referring to the for loop ?
If yes, how did you get priceTier and you checking for priceTier[tier${k}], you can simply have

if(priceTier[`tier${k}`]) // This will make sure it's not undefined or null

If you don’t mind sharing the full function content so we can both look into a fix

Yes I am referring to the for loop.
The whole function is:


const handleOk = async () => {
        setConfirmLoading(true);
        let ids = [];
        let listPrices = []
        for(let k = 0; k<props.numberOfTiers;k++) {
            if(priceTier[`tier${k}`]){
                listPrices.push(priceTier[`tier${k}`]);
                ids.push(k);
            }
        }
        console.log(ids, listPrices);
        let options = {
            contractAddress: props.contractAddress,
            functionName: "setPriceForAll",
            abi: props.abi,
            params : {
                _ids : [0,1], // with default parameters the function will work properly
                _priceList : [100,25], // with those params == [ids] and [listPrices] it will not. 
            }
        }
        console.log(options);
        try {
            let tx = await Moralis.executeFunction(options)
            await tx.wait()
            .then(() => {
                console.log(tx); 
            })
        } catch (error) {
            console.log(error.message);
        } finally {
            setConfirmLoading(false);
        }
    }

You need to add the import import { useWeb3ExecuteFunction } from "react-moralis";

You also need to add the hook const { fetch } = useWeb3ExecuteFunction();

Then you can restructure your function

const handleOk = async () => {
  setConfirmLoading(true);
  let ids = [];
  let listPrices = [];

  for (let k = 0; k < props.numberOfTiers; k++) {
    if (priceTier[`tier${k}`]) {
      listPrices.push(priceTier[`tier${k}`]);
      ids.push(k);
    }
  }
  console.log(ids, listPrices);

  let options = {
    contractAddress: props.contractAddress,
    functionName: "setPriceForAll",
    abi: props.abi,
    params: {
      _ids: [0, 1], // with default parameters the function will work properly
      _priceList: [100, 25], // with those params == [ids] and [listPrices] it will not.
    },
  };
  console.log(options);

  fetch({
    params: options,
    onSuccess: (tx) =>
      tx.wait().then((newTx) => {
        console.log(newTx);
      }),
    onError: (error) => console.log(error.message),
    onComplete: () => setConfirmLoading(false),
  });
};
1 Like

Okay, you are right it’s working now :slight_smile: thanks
I have a last question is there a way by using

const { fetch } = useWeb3ExecuteFunction();

to have my confirm button loading while the transaction did not complete? Because right now as soon as I confirm my transaction the button goes back to “Ok” and don’t load even though tx is still processing. I tried to use the isFetching but it does not work.

EDIT: Also do you know why using speciific Moralis module from react si better than just using Moralis from useMorals?

How are you using isFetching with your button in code? Try using isLoading as well.

I’m not sure what you mean exactly as useMoralis is from react-moralis.

react-moralis uses the base Moralis library and makes it easier to use Moralis functionality and handle fetched data in React apps.

Hi, so isFetching is a boolean true | false button spins if is fetching and stop if not. The thing is that as soon as you start the execute the tx is fetching goes back to false.

The difference between using execute function from Moralis (called by useMoralis) and calling the hook useExecuteFunction from react-moralis

It’s the same, but different syntax. The hook best for reactJS.

A little workaround is I can see you have a setConfirmLoading(true);, you can set it to false in onSuccess and onError rather.