Web3 contract method callback firing endlessly

Something weird and new happening after upgrading moralis and server, when I use this contract method the callback fires endlessly!

      marketContract.value.methods.addItemToMarket(props.token_address, props.token_id, askingPriceWei.value, 0).send({from: sender})
      .on('receipt', receipt => {
        console.log('receipt:', receipt)
      })
      .on('error', (err) => {
        console.log('error selling nft:', err)
      })
    }

Contract:

  /**
    * @dev Adds a new item to the market
    * @param token_address - nft erc721 address
    * @param token_id - nft token id
    * @param askingPrice - asking price in wei
    * @param expiresAt - time in hours when sale end
    */
  function _addItemToMarket(
    address token_address,
    uint256 token_id,
    uint256 askingPrice,
    uint256 expiresAt
  ) 
    internal
  {
    require(askingPrice > 0, "Price should be greater than 0");
    if (expiresAt != 0) require(expiresAt > block.timestamp + 1 minutes, "Listing should be more than 1 minute in the future");
    address owner_of = IERC721Upgradeable(token_address).ownerOf(token_id);
    bytes32 item_id = keccak256(
      abi.encodePacked(
        block.timestamp,
        owner_of,
        token_id,
        token_address,
        askingPrice
      )
    );
    marketItemByTokenId[token_address][token_id] = MarketItem({
      item_id: item_id,
      token_id: token_id,
      token_address: token_address,
      owner_of: owner_of,
      askingPrice: askingPrice,
      expiresAt: expiresAt
    });


    emit ItemAdded(
      item_id,
      token_id,
      token_address,
      owner_of,
      askingPrice,
      expiresAt
    );
  }

I’m in the middle of testing new contracts, while also upgrading code and dependencies, but it doesn’t make sense… what could cause the callback to keep firing?

server v0.0.255 & “moralis”: “^0.0.39”

Shouldn’t that send method make a request to MetaMask in order to send the transaction? How could it fire endlessly?

yes this is after the transaction is succesful, after metamask, after tx confirmation…
It’s the .on('receipt') event that fires until you close the page haha.

Could you share the full code?

And how do you declare web3 variable?

Solved it :slight_smile: guess I needed a push to dive deeper thanks.
For those interested:

Actually it turns out that it’s being caused by 2 transactions after each other like this:

    const sell = async () => {
      const sender = user.value.get('ethAddress')
      await tokenContract.value.methods.approve(marketContractHash.value, props.token_id).send({from: sender})
      .on('receipt', receipt => {
        console.log('receipt:', receipt)
      })
      .on('error', (err) => {
        console.log('error approving nft:', err)
      })
      await marketContract.value.methods.addItemToMarket(props.token_address, props.token_id, askingPriceWei.value, 0).send({from: sender})
      .on('receipt', receipt => {
        console.log('receipt:', receipt)
      })
      .on('error', (err) => {
        console.log('error selling nft:', err)
      })
    }

The second console.log('receipt:', receipt) keeps having new callbacks, actually for every block confirmation as it turns out. Await no work like this.
This works of course, but ugly:

    const sell = async () => {
      waitingForSell.value = true
      const sender = user.value.get('ethAddress')
      tokenContract.value.methods.approve(marketContractHash.value, props.token_id).send({from: sender})
      .on('receipt', receipt => {
        console.log('approve receipt:', receipt)
        marketContract.value.methods.addItemToMarket(props.token_address, props.token_id, askingPriceWei.value, 0).send({from: sender})
        .on('receipt', receipt => {
          console.log('addItemToMarket receipt:', receipt)
        })
        .on('error', (err) => {
          console.log('error selling nft:', err)
        })
      })
      .on('error', (err) => {
        console.log('error approving nft:', err)
      })
    }

When I use this:

.on('confirmation', (confirmationNumber, receipt) => {
          console.log('confirmationNumber',confirmationNumber);

I can see that each new callback is from a new confirmed block, starts at 0 and adds up until it reaches 24 and stops, might be by design:

This is my final full function that worked out:

const ensureMarketplaceApproved = async (token_id) => {
  const sender = user.value.get('ethAddress')
  const approvedAddress = await tokenContract.value.methods.getApproved(token_id).call()
  if (approvedAddress.toLowerCase() == marketContractHash.value) return true
  await tokenContract.value.methods.approve(marketContractHash.value, token_id).send({from: sender})
  .on('receipt', () => {
    return true
  })
  .on('error', (err) => {
    console.log('ERROR approving token', err);
    resetState()
    emit('close')
    Notify.create({
      type: 'negative',
      message: 'Selling not approved'
    })
    return false
  })
}
const sell = async () => {
  waitingForSell.value = true
  const sender = user.value.get('ethAddress')
  const approved = await ensureMarketplaceApproved(props.token_id)
  if (approved) {
    waitingForConfirmation.value = tokenApproved.value = true
    marketContract.value.methods.addItemToMarket(props.token_address,props.token_id,askingPriceWei.value,expiresAt.value).send({from: sender})
    .on('receipt', (receipt) => {
      console.log('receipt:', receipt)
      if (receipt.transactionHash) sellingTX.value = receipt.transactionHash
      emit('sellingDone', {
        item_id: receipt.events.ItemAdded.returnValues.item_id,
        askingPrice: receipt.events.ItemAdded.returnValues.askingPrice,
        expiresAt: receipt.events.ItemAdded.returnValues.expiresAt,
      })
      Notify.create({
        type: 'positive',
        message: 'Your NFT was succesfully listed on the marketplace'
      })
    })
    .on('error', (err) => {
      console.log('error selling nft:', err)
      resetState()
      emit('close')
      Notify.create({
        type: 'negative',
        message: err.message
      })
    })
  }
}

I had something similar before and never had this issue, but after refactoring always risk of hitting a brick wall :sweat_smile:

1 Like