Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Unable to truffle migrate using a custom web3 provider engine #340

Open
mortimr opened this issue May 4, 2020 · 2 comments
Open

Unable to truffle migrate using a custom web3 provider engine #340

mortimr opened this issue May 4, 2020 · 2 comments

Comments

@mortimr
Copy link

mortimr commented May 4, 2020

Hi, I'm currently facing an issue while trying to deploy my contracts on a live network with truffle using a Ledger device.

Currently, I am able to connect to the device and properly sign and broadcast the first transaction, but it seems truffle is unable to resolve the transaction (while I can see the transaction confirmed).

I am 99% sure that the issue is coming from the web3 provider engine as I managed to deploy the contracts using the HDWallet provider, but I have no clue on what might be the difference in behavior.

This is the LedgerProvider I have:

const Web3 = require('web3');
const FiltersSubprovider = require('web3-provider-engine/subproviders/filters');
const NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker');
const ProviderEngine = require('web3-provider-engine');
const ProviderSubprovider = require('web3-provider-engine/subproviders/provider');
const TransportU2F = require('@ledgerhq/hw-transport-node-hid').default;
const createLedgerSubprovider = require('@ledgerhq/web3-subprovider').default;
const {listen} = require('@ledgerhq/logs');

class LedgerProvider extends ProviderEngine {
    constructor(connector, options, url, headers, debug) {
        super();

        this.addProvider(new FiltersSubprovider());

        this.addProvider(new NonceSubprovider());

        this.addProvider(createLedgerSubprovider(async () => {
            const transport = await TransportU2F.create();

            listen(logs => console.log(logs.type, logs.message));

            return transport
        }, options));

        switch (connector) {
            case 'http': {
                const web3Provider = new Web3.providers.HttpProvider(url, {headers, keepAlive: false});
                web3Provider.sendAsync = (payload, callback) => {
                    console.log(payload.method);
                    return web3Provider.send(payload, callback);
                };
                this.addProvider(new ProviderSubprovider(web3Provider));
                break ;
            }
            case 'ws': {
                const web3Provider = new Web3.providers.WebsocketProvider(url, {headers});
                web3Provider.sendAsync = (payload, callback) => {
                    console.log(payload.method);
                    return web3Provider.send(payload, callback);
                };
                this.addProvider(new ProviderSubprovider(web3Provider));
                break ;
            }
        }
        this.start();
    }

}

And am using the following versions of the packages:

...
        "web3": "1.2.6",
        "web3-provider-engine": "15.0.7",
        "@ledgerhq/hw-transport-node-hid": "5.13.1",
        "@ledgerhq/web3-subprovider": "5.14.0",
        "@ledgerhq/logs": "5.13.1"
...

Truffle dispatches the transaction, and hangs for ever

     > transaction hash:    0x0db54853b3cce673aa71e87c48b8669eed006fe178dca3b736888bfdebad7a8d

  - Blocks: 0            Seconds: 0

I would like to know if someone else has such issues when using truffle + web3-provider-engine, or when trying to use a ledger device with truffle. Might not be the good place to ask this but honestly I cannot find people trying to do the same thing (I tried all ledger provider packages and have no results)

@twt--
Copy link

twt-- commented May 7, 2020

I am having the same issue. Works fine with ledger+ganache and HDWallet, but no luck when trying to hook into rinkeby with ledger. I'm not sure what's causing the issue, but I do have a really horrible workaround that makes it work for me: wait ~30 seconds before calling the eth_getTransactionReceipt:

web3Provider.sendAsync = (payload, callback) => {
  if (payload.method == "eth_getTransactionReceipt") {
     const waitUntil = new Date(new Date().getTime() + 30000);
     while(waitUntil > new Date()){}
  }
  return web3Provider.send(payload, callback);
}

@mortimr
Copy link
Author

mortimr commented May 7, 2020

Hi @twt--,

I managed to make it work by using the following Provider:

const Web3 = require('web3');
const {LedgerSubprovider, Web3ProviderEngine } = require('@0x/subproviders');
const ProviderSubprovider = require('web3-provider-engine/subproviders/provider');
const Eth = require('@ledgerhq/hw-app-eth').default;
const TransportNodeHid = require('@ledgerhq/hw-transport-node-hid').default;

async function ledgerEthereumNodeJsClientFactoryAsync() {
    const ledgerConnection = await TransportNodeHid.create();
    const ledgerEthClient = new Eth(ledgerConnection);
    return ledgerEthClient;
}

class LedgerProvider extends Web3ProviderEngine {
    constructor(options, url, headers, debug) {
        super();

        this.addProvider(new LedgerSubprovider({
            baseDerivationPath: options.derivationPath,
            networkId: options.networkId,
            accountFetchingConfigs: {
                shouldAskForOnDeviceConfirmation: true,
            },
            ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync,
        }));

        const web3Provider = new Web3.providers.HttpProvider(url, {headers, keepAlive: false});
        web3Provider.sendAsync = web3Provider.send;
        this.addProvider(new ProviderSubprovider(web3Provider));

        this.start();
    }

    send(...args) {
        return this.sendAsync(...args);
    }

}

And by using the exact following versions (truffle version is important):

        "truffle": "5.0.18",
        "web3-provider-engine": "15.0.7",
        "@ledgerhq/hw-transport-node-hid": "5.13.1",
        "@ledgerhq/web3-subprovider": "5.14.0",
        "@ledgerhq/hw-app-eth": "5.14.0",
        "@0x/subproviders": "6.0.8"

@Bow0628 Bow0628 mentioned this issue Jul 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants