'Does approve take time to be confirmed, and how to deal with this in BSC?

Hi I am doing BSC DApp using web3 with react. I am very new to this field.

I found after call approve, the transfer(or zapInToken in my case) will not be successful with complaining not enough allowance. So I added wait allowance to be present for 10s, but it seems in many times(50% chance) after 10s the allowance still not present. Please check the below code for more information.

Theoretically, approve will generate a transaction and the time to be present depends. If it is the case, Is it a standard pattern to approve, wait for allowance and transfer?

Thank you!

const bepContract = getContract(getAddress(from), erc20ABI, library, account)
const tx = await bepContract.approve(getAddress(contracts.zap), weiAmount)
if (!tx) {
    throw new Error('Failed to approve transaction')
}
await waitAllowance(bepContract, account, getAddress(contracts.zap), weiAmount, 10) // <-- and it will stuck here in most time, the code waits for the allowance is present
await getZapContract().zapInToken(getAddress(from), weiAmount, getAddress(to)).then(logInfo).catch(logError)

And the waitAllowance is like below

const waitAllowance = async (
  contract: Contract,
  account: string,
  to: string,
  allowanceNeeded: string,
  timesLeft: number
): Promise<void> => {
  if (timesLeft > 1) {
    const currentAllowance = await contract.allowance(account, to)
    // console.log(`I want ${allowanceNeeded}, and current is ${currentAllowance} `)
    const needed = new BigNumber(allowanceNeeded)
    const current = new BigNumber(currentAllowance.toString())
    if (current.isGreaterThanOrEqualTo(needed)) {
      return
    }
    await new Promise((res) => setTimeout(res, 1000))
    await waitAllowance(contract, account, to, allowanceNeeded, timesLeft - 1)
  }
  throw new Error('wait allowance failed for many times.')
}


Solution 1:[1]

I figured out, I need to tx.wait, so the working code like below:

const bepContract = getContract(getAddress(from), erc20ABI, library, account)
const tx = await bepContract.approve(getAddress(contracts.zap), weiAmount)
if (!tx) {
    throw new Error('Failed to approve transaction')
}
const tx = await waitAllowance(bepContract, account, getAddress(contracts.zap), weiAmount, 10)
const txResult = await tx.wait()
if (txResult.status !== 1) {
    throw new Error('Failed approve')
}
const txZap = await getZapContract().zapInToken(getAddress(from), weiAmount, getAddress(to))
const txZapResult = await txZap.wait()
if (txZapResult.status !== 1) {
    throw new Error('Failed zap')
}

Check this doc from more details

Solution 2:[2]

Hours of debugging and realised it is due to the Node I'm using. Changed from getblock to Moralis and worked

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ron
Solution 2 Nagibaba