I have the following code that waits for a transaction to get mined on the Ethereum blockchain.
function waitForMinedTransaction(txHash, tries = 1) {
return new Promise(function(resolve, reject) {
web3.eth.getTransactionReceipt(txHash, function(err, res) {
if (err) reject(err)
if (res) resolve(res)
// nothing yet (retry in 10 sec..)
console.log(`Attempt #${ tries }...`)
if (tries > 60) reject("max_tries_exceeded")
setTimeout(function() { return waitForMinedTransaction(txHash, tries + 1) }, 10000)
})
})
}
The issue is that when the transaction is mined (e.g. after 10 tries), it never gets resolved. I'm sure this has something to do with setTimeout
and the promise chain (where a Promise is return
ed instead of resolve
/reject
ing the current promise) but need some pointers on fixing it.
I would suggest to embed the chaining logic inside the promise constructor callback.
Also make sure that when you resolve or reject, you exit the function to avoid the rest of the code being executed. So put a return
before the calls to resolve
and reject
, not that a return value has any sense, but just to make sure the rest of the function's code is not executed:
function waitForMinedTransaction(txHash) {
return new Promise(function(resolve, reject) {
(function attempt(triesLeft) {
web3.eth.getTransactionReceipt(txHash, function(err, res) {
if (err) return reject(err);
if (res) return resolve(res);
if (!triesLeft) return reject("max_tries_exceeded");
console.log(`No result. Attempts left: #${ triesLeft }...`);
setTimeout(attempt.bind(null, triesLeft-1), 10000);
});
})(60); // number of retries if first time fails
});
}
If you prefer to have new promises in the chain (like you attempted to do), then the trick is to resolve with the chained promise, i.e. with the return value of the the chained call:
function waitForMinedTransaction(txHash, triesLeft = 60) {
return new Promise(function(resolve, reject) {
getTransactionReceipt(txHash, function(err, res) {
if (err) return reject(err);
if (res) return resolve(res);
console.log(`No result. Attempts left: #${ triesLeft }...`);
if (!triesLeft) return reject("max_tries_exceeded");
setTimeout(_ => {
resolve(waitForMinedTransaction(txHash, triesLeft-1));
}, 10000);
});
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With