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