1

I use Truffle to develop locally and run tests with truffle test (letting it create a temporary local blockchain).

In one of my tests I need to sign a message and for that I need the test wallet's privateKey. Unfortunately Truffle's contract() provides only an array of accounts (an array of addresses). I googled and it seems that there is no way to get the private key for those addresses.

So I tried the following:

await web3.eth.accounts.wallet.create(1);
const wallet = web3.eth.accounts.wallet[0];

// ok
const signedMessage = await wallet.sign('message');

// 🆘 fails with "sender account not recognized"
const contract = await MyContract.new({ from: wallet.address }); 

The Issue: The message signer should also be the deployer of the contract but when I try to instantiate the contract as the newly created wallet.address I get the following error:

1) Contract: MyContract
       test case no. 1 :
     Error: Returned error: sender account not recognized
      at Context.<anonymous> (test/my_contract.js:67:43)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)

1 Answer 1

1

We observe that web3 exposes a few wallet functionalities that may not be very clear at first:

  1. web3.eth.accounts / getAccounts()
  2. web3.eth.accounts.wallet

It seems web3.eth.accounts.wallet.create is a utility meant to create accounts on the fly without actually auto-binding them to your local node's account list (credits: previous answer). You could use web3.eth.personal.newAccout() but that still wouldn't give you access to the private key.

Solution

Using the two utilities, we can (1) create a new wallet (2) add it to the "personal" list.

 /** Connect to ganache */
 const web3 = new Web3('http://localhost:7545')

 /** Create the new wallet */
 await web3.eth.accounts.wallet.create(1)
 const wallet = web3.eth.accounts.wallet[0]

 /** Bind the new wallet to the personal accounts */
 await web3.eth.personal.importRawKey(wallet.privateKey, '') // password is empty
 await web3.eth.personal.unlockAccount(wallet.address, '', 10000) // arbitrary duration

 /** Check wallet was added to accounts */
 const accounts = await web3.eth.getAccounts()
 console.log(accounts, wallet.address)

Small caveat here is that if you wanna pursue your contract creation, you also need to fund the new account with some ETH for gas.

3
  • @razgrafe hi, thanks a lot for the pointer! That indeed works. Do you have an idea on how I could then fund the new account? Should I transfer some ETH from an existing testing account?
    – G.G.
    Jan 15, 2022 at 17:28
  • I think so, maybe doing a transfer before importing and unlocking e.g. web3.eth.sendTransaction({to: wallet.address)} so you send funds from the previous default address
    – razgraf
    Jan 15, 2022 at 17:35
  • yep amazing! After asking I figured I should try that :) Thank you again for the help!
    – G.G.
    Jan 15, 2022 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.