MetaMask / web3-provider-engine

A JavaScript library for composing Ethereum provider objects using middleware modules
MIT License
598 stars 328 forks source link

Truffle hangs forever when using ProviderEngine #176

Closed hedin-hiervard closed 7 years ago

hedin-hiervard commented 7 years ago
    const engine = new ProviderEngine();
    engine.addProvider(new WalletSubprovider(wallet, {}));
    engine.addProvider(new FilterSubprovider());
    engine.addProvider(new Web3Subprovider(new Web3.providers.HttpProvider(`SOME_URL`));

    engine.start();

When I use this engine as a provide for Truffle config, everything works as expected and deploys correctly. But truffle process neverfinishes. I suspect some event listeners are still there, but I can't list or remove them.

danfinlay commented 7 years ago

That's correct, you need to ask the engine to clean itself up with engine.stop().

kgritesh commented 7 years ago

@flyswatter where should the engine.stop go inside truffle?

hedin-hiervard commented 7 years ago

@kgritesh It doesn't provide any hooks. Neither I found how to force node to clear event handlers politely. The way I'm using it now is a fork of a truffle command line interface file with added process.exit(0)

danfinlay commented 7 years ago

If you're creating your own programmatic provider engine within a Truffle project, you can call engine.stop() whenever you're done with the provider-engine.

If this is something within the Truffle project itself, this call to engine.stop() would need to be called once everything was deployed and published, since then you could deallocate your blockchain connection and keys.

kgritesh commented 7 years ago

@flyswatter this is my truffle.js

require('babel-register');
const bip39 = require('bip39');
const hdkey = require('ethereumjs-wallet/hdkey');
const ProviderEngine = require('web3-provider-engine');
const WalletSubprovider = require('web3-provider-engine/subproviders/wallet');
const Web3Subprovider = require('web3-provider-engine/subproviders/web3');
const Web3 = require('web3');

// Get our mnemonic and create an hdwallet
const mnemonic = 'accuse extend real hat they eagle worry brisk earn drop deputy guide';
const hdwallet = hdkey.fromMasterSeed(bip39.mnemonicToSeed(mnemonic));

// Get the first account using the standard hd path.
const hdWalletPath = "m/44'/60'/0'/0/";
const wallet = hdwallet.derivePath(`${hdWalletPath}0`).getWallet();
const address = `0x${wallet.getAddress().toString('hex')}`;
console.log('address', address);

const providerUrl = 'https://ropsten.infura.io/9ehOllb9H1NKBMeOP9xc';
const engine = new ProviderEngine();
engine.addProvider(new WalletSubprovider(wallet, {}));
engine.addProvider(new Web3Subprovider(new Web3.providers.HttpProvider(providerUrl)));
engine.start(); // Required by the provider engine.
console.log('Engine Started');

module.exports = {
  networks: {
    ropsten: {
      network_id: 3,    // Official ropsten network id
      provider: engine, // Use our custom provider
      from: address,
      gas: 3000000
    },
    development: {
      host: 'localhost',
      port: 8545,
      network_id: '*'
    }
  }
};

and when i run

 truffle migrate --network ropsten

  Engine Started
Using network 'ropsten'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0xe4f97415585fadda23568840dc6680dce923323fe3873bfc4a1eb2df5a485a69

this is the output i get. It just hangs. I have two migrations if the issue is with engine.stop then atleast 2nd migration should also run right and then it should hang. But it just hangs after deploying 1st migration. Can you help me with this?

danfinlay commented 7 years ago

Oh that's interesting, that makes sense. I'm not sure the truffle.js file ever expected to need an "after install" callback, which is what you really need here. Pinging @tcoulter. I've opened this as a feature request on Truffle for you.

If you wanted to be risky/hacky, you could do something like

setTimeout(function(){ engine.stop() }, 2000)

And as long as the deploy worked in 2 seconds, that would be safe. Also, force quitting afterwards is probably safe.

evgenynacu commented 7 years ago

@kgritesh add engine.addProvider(new FilterSubprovider()); as in the first post here. infura doesn't support eth_newBlockFilter requests, so we need FilterSubProvider

rguikers commented 7 years ago

@danfinlay , so engine.stop should be called. But there is no placeholder anywhere to detect the end of the migrate or test script. please advise, because a custom provider is needed in more complex projects to my opinion. Thanks,

danfinlay commented 7 years ago

I already advised. There are two options: adding an after hook to truffle, or hacking on a stop call with a timeout.