trufflesuite / truffle

:warning: The Truffle Suite is being sunset. For information on ongoing support, migration options and FAQs, visit the Consensys blog. Thank you for all the support over the years.
https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat?utm_source=github&utm_medium=referral&utm_campaign=2023_Sep_truffle-sunset-2023_announcement_
MIT License
14.02k stars 2.32k forks source link

MyEvent.watch() returns `watch is not a function` error (V5) #1254

Closed tarekskr closed 6 years ago

tarekskr commented 6 years ago

Issue

Using MyEvent.watch() now raises an error.

Steps to Reproduce

componentDidMount = async () => {
    try {
      // Get network provider and web3 instance.
      const web3 = await getWeb3();

      // Get the contract instance.
      const Contract = truffleContract(MyContract);
      Contract.setProvider(web3.currentProvider);
      const contractInstance = await Contract.deployed();

      // Watch for MyEvent
      contractInstance.MyEvent().watch((error, result) => {});

    } catch (error) {
      console.log(error);  // always gives: TypeError: contractInstance.MyEvent(...).watch is not a function
    }
  };

Expected Behavior

As of truffle-contract v.1.1.11, the above code worked flawlessly.

Actual Results

Now it gives the following error:

TypeError: contractInstance.MyEvent(...).watch is not a function

Environment

cgewecke commented 6 years ago

@tarekskr Hi thanks for noting this.

4.0.0-next.0 uses Web3 1.0 and has a number of API changes detailed in the new Truffle beta release notes.

watch is no longer supported. Instead you can use an EventEmitter-like interface (requires that you have websockets enabled in your network config) or a callback (for http: see the Web3 1.0 docs here for more.)

tarekskr commented 6 years ago

Thank you so much @cgewecke for getting back to me.

I followed your recommendation and was able to eliminate the error. The event code however doesn't seem to ever get called. Here is what my code looks like now:

watchTokenTransferEvent(tokenInstance) {
    // watch the Transfer event
    tokenInstance.Transfer()
    .on('data', event => {
        var fromAddress = event.returnValues.from;  

        // this *never* gets called
        console.log("******fromAddress: " + fromAddress);
        }
      }
    );
  }

I've also updated my networks config to enable websockets as follows:

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "*", // Match any network id
      websockets: true
    },
    ropsten: {
      provider: function() {
        return new HDWalletProviderPrivkey(ropstenPrivateKeys, "https://ropsten.infura.io/");
      },
      network_id: '3',
      websockets: true,
      from: ropstenAccount,
      gas: 4612388 // Gas limit used for deploys
    },
    rinkeby: {
      provider: function() {
        return new HDWalletProvider(rinkebyMnemonic, "https://rinkeby.infura.io/");
      },
      network_id: '4',
      websockets: true,
      from: rinkebyAccount,
      gas: 4612388 // Gas limit used for deploys
    }
  }
};

Am I still missing anything here?

cgewecke commented 6 years ago

@tarekskr There are a few things here: I think port 7545 might be a problem. . . that's the automatically launched ganache instance that isn't really configurable unfortunately.

Could you try again after launching ganache-cli separately on the command line at 8545 and changing your development config port to the same?

The other thing to check might be the truffle-contract events tests which have some working examples.

Finally - to use websockets on infura you have to connect to their websockets endpoints (ex: wss://ropsten.infura.io). Also be aware that these are less reliable than http at the moment.

tarekskr commented 6 years ago

Thanks @cgewecke , I am actually using MetaMask to access my daap on Ropsten.

So I used the callback tokenInstance.Transfer(function(error, event) { instead of .on('data', event => { and I actually got the following error:

Error: The current provider doesn't support subscriptions: MetamaskInpageProvider

With further research, it turns out MetaMask does not support websockets yet.

My question remains, how can I listen for events now like I used to do before upgrading truffle? Thanks a ton.

cgewecke commented 6 years ago

@tarekskr Ah!! I didn't know the callback was also websockets - my understanding was that it was a polling fallback. I'll look into this further today.

cgewecke commented 6 years ago

@tarekskr It looks like Web3 only supports websockets, so there's a fundamental incompatibility with MetaMask at the moment. . . will ping this issue if I see a resolution (or cool workaround).

tarekskr commented 6 years ago

Thanks a lot @cgewecke . I actually pinged MetaMask and they said they should have something rolled out next week 🤞 https://github.com/MetaMask/metamask-extension/pull/4279#issuecomment-418810239

gnidan commented 6 years ago

@tarekskr looks like that MetaMask PR got merged. Can this be closed? Thanks!

tarekskr commented 6 years ago

@gnidan awesome! Thanks again @cgewecke for all your help.