I'm following a tutorial to make transactions. The tutor does it using below web3.js and react.js code block.

stakeTokens = (amount) => {
this.setState({ loading: true })
this.state.daiToken.methods.approve(this.state.tokenFarm._address, amount).send({ from: this.state.account }).on('transactionHash', (hash) => {
  this.state.tokenFarm.methods.stakeTokens(amount).send({ from: this.state.account }).on('transactionHash', (hash) => {
    this.setState({ loading: false })


But when I remove ".on('transactionHash', callback())" part, still transactions are happening without any problem. This is my code block.

stakeTokens = async (amount) => {
this.setState({ loading: true });
await this.state.daiToken.methods
  .approve(this.state.tokenFarm._address, amount)
  .send({ from: this.state.account });
await this.state.tokenFarm.methods.stakeTokens(amount).send({from : this.state.account})
this.setState({loading : false});


So I'm wondering why we need on('transactionHash', callback()) when we can do the same thing without it. And as you can understand by looking at my reputation amount, I'm a newbie to this ethereum thing. So someone please explain to me why we need this on() method?

1 Answer 1


Basically .send() function have several stages between start and completion

Here are intermediate states

sending returns payload: Object: Fired immediately before transmitting the transaction request.

sent returns payload: Object: Fired immediately after the request body has been written to the client, but before the transaction hash is received.

"transactionHash" returns transactionHash: String: Fired when the transaction hash is available.

"receipt" returns receipt: Object: Fired when the transaction receipt is available. Receipts from contracts will have no logs property, but instead an events property with event names as keys and events as properties. See getPastEvents return values for details about the returned event object.

"confirmation" returns confirmation: Number, receipt: Object, latestBlockHash: String: Fired for every confirmation up to the 24th confirmation.

"error" returns error: Error: Fired if an error occurs during sending. If the transaction was rejected by the network with a receipt, the receipt will be available as a property on the error object.

Basic difference between your and instructor's implementation is

instructor is waiting for specific event transactionHash, to be generated before proceeding whereas you're not caring about any thing other than completion of transaction, you send transaction and when it is complete you proceed with other stages of your program.

in this specific scenario you're waiting more than the instructor.

You can read more about why ethereum have callbacks in addition to promises here. Callbacks Promises Events

Ethereum as a blockchain has different levels of finality and therefore needs to return multiple “stages” of an action. To cope with requirement we return a “promiEvent” for functions like web3.eth.sendTransaction or contract methods. This “promiEvent” is a promise combined with an event emitter to allow acting on different stages of action on the blockchain, like a transaction.

PromiEvents work like a normal promises with added on, once and off functions. This way developers can watch for additional events like on “receipt” or “transactionHash”.

web3.eth.sendTransaction({from: '0x123...', data: '0x432...'})
.once('sending', function(payload){ ... })
.once('sent', function(payload){ ... })
.once('transactionHash', function(hash){ ... })
.once('receipt', function(receipt){ ... })
.on('confirmation', function(confNumber, receipt, latestBlockHash){ ... })
.on('error', function(error){ ... })
    // will be fired once the receipt is mined
  • So that means I'm waiting for the 'confirmation' while instructor is waiting for only 'transactionHash'?
    – Sapthaka
    Commented Dec 10, 2021 at 3:04
  • @Jagath Yes you're waiting for transaction to complete, and instructor is being optimistic, he thinks transaction hash has been generated now it will eventually be confirmed by network i don't have to worry about it anymore and continues with it's code. but if there is a scenario where you need to 100% sure that transaction was success then your approach would be better. Commented Dec 11, 2021 at 0:04
  • @Faizan Ul Haq I tried using ".on('confirmation', function(confNumber, receipt, latestBlockHash){ ... })". But the transaction didn't happen. No errors and also no transaction happened. Have you any clarification please?
    – Sapthaka
    Commented Jan 29, 2022 at 5:07
  • 1
    This is supposed to work like that but here is an open issue that might give you some insight to the problem, github.com/ChainSafe/web3.js/issues/2104 if you want better answers I would advise you to open another question. Commented Jan 30, 2022 at 11:24
  • 1
    I got the reason for confirmation is not working. Because confirmation is working only until 24th confirmation. After that confirmation will not work. Read the confirmation point of this link carefully.web3js.readthedocs.io/en/v1.2.11/…
    – Sapthaka
    Commented Dec 22, 2022 at 9:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.