MetaMask / metamask-extension

:globe_with_meridians: :electric_plug: The MetaMask browser extension enables browsing Ethereum blockchain enabled websites
https://metamask.io
Other
12.03k stars 4.91k forks source link

Metamask web3 instance's contract deploy callback function not fired twice #2426

Closed tina1998612 closed 5 years ago

tina1998612 commented 7 years ago

From the official doc of web3js API about contract deploy, the callback function of MyContract.new should be fired twice(one for the transaction hash and the other for the contract address after it is deployed).
However, using the metamask's web3 instance, this callback function seems to be fired only once. Namely, the contract address is not printed even after the contract is mined, and I can only view the contract address within the metamask extension itself.
The problem is, if not having the original callback function settings(the one that is fired twice), how can I get the contract address efficiently after the contract is mined? (without using setTimeout)
I'm trying to write a client-slide contract deploy utility script which will return the contract address once deployed with metamask. Is it possible with the current metamask web3 library? Or this issue is not related to the library?

Any help will be much appreciated!

KPull commented 7 years ago

I've noticed this issue as well and it is a genuine problem. I believe by polling using getTransactionReceipt, it should be able to determine whether the contract has been deployed (and where).

However, remember that DApps will not be able to tell whether web3 is injected by MetaMask or not. Having a hack such as the one described above, that is specifically for MetaMask, is undesirable.

skozin commented 6 years ago

I believe that this issue prevents truffle-contract from working properly with MetaMask: it doesn't resolve promises of successfully deployed contracts. The issue is only present when web3 is pointed to MetaMask's provider.

Here is the code of truffle-contract's callback function:

var intermediary = function(err, web3_instance) {
  if (err != null) {
    reject(err);
    return;
  }

  if (err == null && web3_instance != null && web3_instance.address != null) {
    accept(new self(web3_instance));
  }
};

As you can see, it checks web3_instance.address (which is not set on the first call) and ignores the call if it's not set, so the promise ends up never being resolved.

yarrumretep commented 6 years ago

+1 on this issue

domharrington commented 6 years ago

I had to fallback to using web3 directly to create contracts https://github.com/trufflesuite/truffle-contract/issues/70#issuecomment-355376332

faeezshaikh commented 6 years ago

Any updates on this issue? Still observing in ver 3.14.1

derekchiang commented 6 years ago

To restate the significance of this issue: the second callback provides an instance of the contract that has its methods mapped to contract functions. Without it, it's impossible to actually call any functions on the contract, rendering the deployed contract useless.

derekchiang commented 6 years ago

In case it helps: the same issue occurs in both Chrome and Firefox.

derekchiang commented 6 years ago

The same issue occurs on both Rinkeby and Ganache (local).

domharrington commented 6 years ago

@derekchiang the workaround here works, and you can get the contract instance: https://github.com/trufflesuite/truffle-contract/issues/70#issuecomment-355376332

bdresser commented 5 years ago

Hey folks, closing this issue due to inactivity, please let me know if you're still having trouble.