truffle
truffle copied to clipboard
Provider factory in truffle config should be able to operate asynchronously
When using clients/networks other than Ganache, it can be advantageous to use a provider like HDWalletProvider. These providers are initialized with some secret (such as a mnemonic or private key), and automatically sign outbound transactions using one or more accounts derived from this secret.
Truffle handles this today by allowing the user to specify a provider function in a network config instead of a host and port. This provider function is meant to synchronously return an instance of Provider for truffle to use internally with its own instance of web3.
Because the provider must be returned synchronously, the user is limited in their options for how they can retrieve a secret with which to construct their provider. Should they wish to prompt a user for a password to decrypt a wallet file, or conduct any other asynchronous operations, they cannot. Instead truffle should allow this provider factory function to optionally return a Promise which resolves to an instance of Provider instead of returning the Provider instance directly.
Example of how this functionality might be used:
const prompt = require('prompt');
const fs = require('fs');
const Wallet = require('ethereumjs-wallet');prompt.start();
const pify = require('pify');
// fork of truffle-hdwallet-provider which accepts a private key as the first argument
// see https://github.com/rhlsthrm/truffle-hdwallet-provider-privkey for more info
const HDWalletProvider = require('truffle-hdwallet-provider-privkey');
var schema = {
properties: {
walletFilename: {
//validator: /^[a-zA-Z0-9\-]+$/,
//warning: 'Wallet name must be only letters, numbers or dashes',
required: true,
},
password: {
hidden: true,
required: true,
}
}
};
module.exports = {
networks: {
mainnet: {
provider: async () => {
let result = await pify(prompt.get)(schema)
let strJson = fs.readFileSync(result.walletFilename, 'utf8');
let wallet = Wallet.fromV3(strJson, result.password);
this.privKey = wallet.getPrivateKey();
return new HDWalletProvider([privKey.toString('hex')], 'https://mainnet.infura.io:8545');
},
network_id: "1"
}
}
};
Is this supported?
EDIT: Spoke to @gnidan and this is not supported unfortunately. Env vars is an option probably.
Was the functionality @benjamincburns proposed in his commits unacceptable in some way? (Curious because I'm thinking of using it in a fork.)
@coventry why fork?
Either way, I imagine it'd be almost trivial to write an abstract provider which calls an init method on the first call to send. You'd probably want to add some kind of locking mechanism to it so that you don't init multiple times in the case that multiple calls get pipelined. I'll see about adding one somewhere once the EIP-1193 dust settles, provided nobody else beats me to the punch.
@gnidan it looks like this issue was closed but the PR I submitted never made it in. This means that users still can't have async logic in their provider initialization code, so they can't, for example, prompt for a password to unlock an encrypted wallet file.
If this has been implemented, perhaps the docs should be updated to reflect this here?
https://www.trufflesuite.com/docs/truffle/reference/configuration#providers
I can't work out whether this is implemented. @gnidan ?
@elenadimitrova IIRC we ended up needing to revert that PR because of complexities it introduced. I'll re-open this.
Hey @elenadimitrova, we're trying to evaluate the priority of this task and wanted to ask how important of a feature this would be for you guys. Would this be a super useful feature?
It is blocking for us to move to truffle atm. We are using an async method to get the private key used to instantiate the HDWalletProvider:
staging: {
provider: async () => {
const { pkey, infuraKey } = await getKeys();
return new HDWalletProvider(pkey, `https://mainnet.infura.io/v3/${infuraKey}`);
},
network_id: 1, // mainnet
gas: _gasLimit,
gasPrice: _gasPrice,
},
This async method is here, getting the key from AWS.
Ok, thanks @elenadimitrova for letting us know! We'll try and get it in the pipeline.
A gentle nudge as this is one of the two blockers to move the argent-contracts repo to truffle. Let me know if you need any help with it.
Thanks @elenadimitrova!
Previously this may not have been feasible due to callback hell. This is probably worth revisiting to determine whether this is doable.