1

I want stop listening metamask transaction event after getting transaction hash.

This is my code.

const transaction = await contract.methods
        .contractMethod(value)
        .send({ from: address, value: ethValue })
        .on("transactionHash", async (txhash: string) => {
          return txHash
        })

I want to stop listening a transaction after transactionHash, however this code listen until transaction is confirmed.

Is there any way to stop listening transaction event after getting transaction hash?

Also, this is my related code with this problem.

<template>
 ....
</template>


import { sendTransaction } from "@/utils/trancaction";

export default defineComponent({
    name: "Form",
    setup() {
        const state = reactive<{
            ethValue: any;
            modal: boolean;
            error: {
                ethValue: string;
            };
        }>({
            ethValue: 0,
            boolean: true,
            error: {
                ethValue: ""
            }
        });

        const confirm = async () => {
            const transactionHash = await sendTransaction(state.icbValue, state.ethValue);
            console.log(2, transactionHash);
            state.modal = false;
        };

        return {
            confirm,
        };
    }
});
</script>

And I tried three different ways.

import { contractAbi } from "./contract-abi";
import Web3 from "web3";

export const sendTransaction = async (icbValue: number, ethValue: number) => {
    await window.ethereum.enable().catch((error: any) => {
        console.log(error);
    });
    const web3 = new Web3(Web3.givenProvider);
    const accounts = await web3.eth.getAccounts();
    const address = accounts[0];
    const contract = await new web3.eth.Contract(contractAbi, "0xa8f6D9A3bF52941691604b0f76455b41c9f3Fc60");
    
    // 1. using once with methods
    const transaction = await contract.methods
        .contractMethod(value)
        .send({ from: address, value: ethValue })
        .once("transactionHash", async (txhash: string) => {
          return txHash
        })
    
    // 2. using callback with sendTrancsaction
    const trancactionHash = await web3.eth.sendTransaction(
      {
          from: address,
          to: "contract address",
          value: ethValue,
          data: functionData // deploying a contracrt
      })
      .once("transactionHash", function(hash) {
        console.log("hash", hash);
        return;
      })


    // 3. using callback with sendTrancsaction
    const functionData = await contract.methods
        .contractMethod(value)
        .encodeABI({ from: address, value: ethValue });

    const trancactionHash = await web3.eth.sendTransaction(
        {
            from: address,
            to: "contract address",
            value: ethValue,
            data: functionData // deploying a contracrt
        },
        function(error, hash) {
            console.log("hash", hash);
            return hash;
        }
    );

};

1 Answer 1

3

Since you are using .on("transactionHash"), your code will actually listen only for the transaction hash, which doesn't necessarily mean that it is confirmed (as compared to .on("receipt") or .on("confirmation").

In any case, you are probably looking for the .once function within the promise:

const transaction = contract.methods
        .contractMethod(value)
        .send({ from: address, value: ethValue })
        .once("transactionHash", async (txhash: string) => {
          return txHash
        });

You may decide using .on or .once depending on the event type:

web3.eth.sendTransaction({from: '0x123...', data: '0x432...'})
.once('transactionHash', function(hash){ ... })
.once('receipt', function(receipt){ ... })
.on('confirmation', function(confNumber, receipt){ ... })
.on('error', function(error){ ... })
.then(function(receipt){
    // will be fired once the receipt is mined
});
4
  • Thank you for your comment. I tried using once instead of using on, but I could not quit listening after getting transaction hash.
    – gnxvw
    Commented Dec 18, 2020 at 23:48
  • 1
    Hmm, the callback should normally end if using '.once'. When you say 'could not quit listening', how do you exactly consider that you are still listening? I guess that can also depend on how you call this method, what you do after calling it, etc. Commented Dec 19, 2020 at 0:00
  • Thank you! I added my related code. I want to close a modal after getting a transaction hash with metamask. In my code, I fired sendTransaction to get transaction hash, but I could not fire state.modal = false; until transaction will be confirm.
    – gnxvw
    Commented Dec 19, 2020 at 0:25
  • Looks like an issue more related on how you manage the state within your application. Just to check if it is not web3 related, try to comment everything inside sendTransaction(), put a setTimer of 5 seconds and then return any random text to see if the modal is closed. Commented Dec 20, 2020 at 18:48

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.