web3 / web3.js

Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.
https://web3js.org/
Other
19.3k stars 4.95k forks source link

sendSignedTransaction failing when calling getTransactionReceipt #1255

Closed dristic closed 5 years ago

dristic commented 6 years ago

I am signing and calling a transfer method on an ERC20 contract like so:

web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
    console.log('signed transaction', signed);

    var transaction = web3.eth.sendSignedTransaction(signed.rawTransaction);

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

    transaction.on('transactionHash', hash => {
      console.log('hash', hash);
    });

    transaction.on('receipt', receipt => {
      console.log('reciept', receipt);
      res.json({ receipt });
    });

    transaction.on('error', console.error);
});

The transaction actually works just fine but it fails around here:

utils._fireError({message: 'Failed to check for transaction receipt:', data: err}, defer.eventEmitter, defer.reject);

I dug in a bit and added some logging and it looks like some code is polling on getTransactionReceipt from the server which seems to fail when called for a pending transaction:

failed Error: Returned error: unknown transaction
    at Object.ErrorResponse (<omitted>/node_modules/web3-core-helpers/src/errors.js:29:16)
    at <omitted>/node_modules/web3-core-requestmanager/src/index.js:137:36
    at XMLHttpRequest.request.onreadystatechange (<omitted>/node_modules/web3-providers-http/src/index.js:64:13)
    at XMLHttpRequestEventTarget.dispatchEvent (<omitted>/node_modules/xhr2/lib/xhr2.js:64:18)
    at XMLHttpRequest._setReadyState (<omitted>/node_modules/xhr2/lib/xhr2.js:354:12)
    at XMLHttpRequest._onHttpResponseEnd (<omitted>/node_modules/xhr2/lib/xhr2.js:509:12)
    at IncomingMessage.<anonymous> (<omitted>/node_modules/xhr2/lib/xhr2.js:469:24)
    at IncomingMessage.emit (events.js:164:20)
    at endReadableNT (_stream_readable.js:1062:12)
    at process._tickCallback (internal/process/next_tick.js:152:19)

I'm using geth and node locally to run the transaction and checking the balance appears that the transaction actually completed. I also get a hash of the transaction and see the log in geth for submitting the transaction but web3 never gives me a confirmation.

dristic commented 6 years ago

Here is the corresponding geth call where the error comes from: https://github.com/ethereum/go-ethereum/blob/8c33ac10bff32d082facfd274188334a3236a4e7/internal/ethapi/api.go#L1007

Hitmanv commented 6 years ago

have you solve this? I ran into the same issue

georgechr commented 6 years ago

Also ran into the same issue, transactions actually goes through but I get the same error

yograterol commented 6 years ago

I fixed it reverting the last change of that file https://github.com/EthereumCommonwealth/go-callisto/commit/a2605686e927d49bde400aab2b38d02366f7b329

If you are using Geth from the source code you could make it change

dristic commented 6 years ago

It looks like this library probably needs to be updated to not make the request until it knows the transaction is available.

vbaranov commented 6 years ago

I am sending transactions with MetaMask v.3.13.3 and has the same issue (Failed to check for transaction receipt) with web3@1.0.0-beta.27 ? Are any ideas how to solve this?

dristic commented 6 years ago

Turns out you can bypass the method entirely and send it yourself

const method = web3.eth.sendSignedTransaction.method;
let payload = method.toPayload([signed.rawTransaction]);

method.requestManager.send(payload, (result) => {
  // if result.error, handle
});
Andromelus commented 6 years ago

Can you elaborate about your method? web3js 1.0 documentation does not mention anything about sendSignedTransction.method

dristic commented 6 years ago

This is basically taken from the source code. There is a number of things going on in there but when you break down the statements this is pretty much all the method does under the hood.

zhs007 commented 6 years ago

My code is like this,if get ‘unknown transaction’ wait a moment try again,It‘s work.

    _sendTransaction(params, callback) {
        const method = web3.eth.sendTransaction.method;
        let payload = method.toPayload([params]);

        method.requestManager.send(payload, (err, result) => {
            callback(err, result);
        });
    }

    _getTransactionReceipt(params, callback) {
        const method = web3.eth.getTransactionReceipt.method;
        let payload = method.toPayload([params]);

        method.requestManager.send(payload, (err, result) => {
            if (err && err.message == 'Returned error: unknown transaction') {
                setTimeout(() => {
                    this._getTransactionReceipt(params, callback);
                }, DELAY_TIME);

                return ;
            }

            callback(err, result);
        });
    }
            this._sendTransaction(tobj, (err, result) => {
                if (!err) {
                    this._getTransactionReceipt(result, (err1, ret1) => {
                        console.log('err ' + err1);
                        console.log('ret ' + JSON.stringify(ret1));
                    });
                }
            });
justindthomas commented 6 years ago

Recently tried moving from infura to my own Ethereum (geth) node and began running into this problem. Switched back to infura until it's resolved.

Will this ultimately be a change in web3 akin to the suggestion by @zhs007 above, or does it need to be a fix to geth?

Fi1osof commented 6 years ago

Got same error.

ghost commented 6 years ago

Why does this started to happend today ? It was not being an issue. Weird. Any ideas?

icetique commented 6 years ago

Got same error, no issues before. It seems it is not related to the application code.

Unhandled rejection Error: Failed to check for transaction receipt: {} at Object._fireError (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-utils\src\index.js:56:17) at C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-method\src\index.js:259:23 at tryCatcher (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\util.js:16:23) at Promise._settlePromiseFromHandler (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\promise.js:497:31) at Promise._settlePromise (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\promise.js:555:18) at Promise._settlePromise0 (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\promise.js:600:10) at Promise._settlePromises (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\promise.js:679:18) at Async._drainQueue (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\async.js:125:16) at Async._drainQueues (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\async.js:135:10) at Immediate.Async.drainQueues [as _onImmediate] (C:\Users\xxx\Server\Apache24\htdocs\xxx\node_modules\web3-core-promievent\node_modules\bluebird\js\release\async.js:16:14) at runCallback (timers.js:789:20) at tryOnImmediate (timers.js:751:5) at processImmediate [as _immediateCallback] (timers.js:722:5)

SeriousAnt commented 6 years ago

Same error here

icetique commented 6 years ago

After update to Geth 1.8.2 this is no longer the issue for me.

thinhlvv commented 6 years ago

I got my solution for this. I removed nonce + 1 => nonce in init transaction object. Because nonce is sequence.

wwaayyaa commented 6 years ago

same error. when i got this error, i can see the tx in explorer. and 3mins after, the tx is comfirmed.

yyy999 commented 6 years ago

Error: Failed to check for transaction receipt: {} at Object._fireError (E:\mytoken\node_modules\web3-utils\src\index.js:56:17) at E:\mytoken\node_modules\web3-core-method\src\index.js:260:23 at

imhari213 commented 6 years ago

Using version "web3": "^1.0.0-beta.27" and control the asynchronous behavior of Nodejs while getting the nonce works for me

May Be following code helps var n = async function m(){ var x = await web3.eth.getTransactionCount(address) txOptions = { chainId: 4, nonce: await web3.utils.toHex(x), gasLimit: await web3.utils.toHex(5000000), gasPrice: await web3.utils.toHex(web3.utils.toWei('10', 'gwei')), to: contractAddress }

console.log(txOptions); console.log(txOptions.nonce.length); console.log(n); var s = "ariprasad"; var rawTx = txutils.functionTx(ABI, 'set', ["Ram"], txOptions); console.log(rawTx); sendRaw(rawTx);

}

//calling method n();

Fi1osof commented 5 years ago

This works for me:

return new Promise((resolve, reject) => {

  web3.eth.sendSignedTransaction("0x" + serializedTx.toString('hex'), (error, txHash) => {
    // console.log(chalk.green("sendSignedTransaction error, txHash"), error, txHash);

    if (error) {
      reject(error);
    }
    // else 
    resolve(txHash);
  })
    .on('confirmation', (confirmationNumber, receipt) => {
      console.log(chalk.green('confirmation'), confirmationNumber);
    })
    .on('error', reject);

});

Full code

mryellow commented 5 years ago

@Fi1osof return to break control flow for the else.

    if (error) {
      return reject(error);
    }
    // else 
    return resolve(txHash);
Fi1osof commented 5 years ago

@mryellow thanks, i will

mryellow commented 5 years ago

Note same thing different code-style in one above, can return void in the "first" condition:

if (error) {
  reject(error);
  return;
}
resolve(txHash);
Fi1osof commented 5 years ago

@mryellow , thanks again :) Did so. Works without errors.

anisurrahman072 commented 1 year ago

I solved this by this simple code. Thanks @dristic 💪🎉

let transactionObject = {
    chainId: 80001,
    to: CONTRACT_ADDRESS,
    data: contract.methods.mint(metadataUrl).encodeABI(),
    gas: 2100000
  }

  let signTransaction = await web3.eth.accounts.signTransaction(
    transactionObject,  '80d7473bbc1b5706bdbe27330e75b89d0f55501d6abd380848028277793e7c50'
  )

  console.log(signTransaction)

  const method = web3.eth.sendSignedTransaction.method
  let payload = method.toPayload([signTransaction.rawTransaction])

  method.requestManager.send(payload, (result) => {
    console.log(payload, result)
  })