0

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;
        }
    );

};

2

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
    Dec 18 '20 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. Dec 19 '20 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
    Dec 19 '20 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. Dec 20 '20 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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