Account Management

When connecting to a remote network via a hosted node such as Infura, the Accounts container will be empty. Before you can perform any transactions you must add a local account to Brownie.

When we use the term local it implies that the account exists locally on your system, as opposed to being available directly in the node. Local accounts are stored in encrypted JSON files known as keystores. If you want to learn more about keystore files, you can read If you want to understand the contents of your json file you can read “What is an Ethereum keystore file?” by Julien Maffre.

You can manage your locally available accounts via the commandline:

$ brownie accounts

Generating a New Account

To generate a new account using the command line:

$ brownie accounts generate <id>

You will be asked to choose a password for the account. Brownie will then generate a random private key, and make the account available as <id>.

Importing from a Private Key

To add a new account via private key:

$ brownie accounts new <id>

You will be asked to input the private key, and to choose a password. The account will then be available as <id>.

Importing from a Keystore

You can import an existing JSON keystore into Brownie using the commandline:

$ brownie accounts import <id> <path>

Once imported the account is available as <id>.

Exporting a Keystore

To export an existing account as a JSON keystore file:

$ brownie accounts export <id> <path>

The exported account will be saved at <path>.

Unlocking Accounts

In order to access a local account from a script or console, you must first unlock it. This is done via the Accounts.load method:

>>> accounts
[]
>>> accounts.load(id)
>>> accounts.load('my_account')
Enter the password for this account:
<LocalAccount object '0xa9c2DD830DfFE8934fEb0A93BAbcb6e823e1FF05'>
>>> accounts
[<LocalAccount object '0xa9c2DD830DfFE8934fEb0A93BAbcb6e823e1FF05'>]

Once the account is unlocked it will be available for use within the Accounts container.

Unlocking Accounts on Development Networks

On a local or forked development network you can unlock and use any account, even if you don’t have the corresponding private key. To do so, add the account to the unlock setting in a project’s configuration file:

networks:
    development:
        cmd_settings:
            unlock:
                - 0x7E1E3334130355799F833ffec2D731BCa3E68aF6
                - 0x0063046686E46Dc6F15918b61AE2B121458534a5

The unlocked accounts are automatically added to the Accounts container. Note that you might need to fund the unlocked accounts manually.

Signing Raw Text Messages (EIP-191)

To sign an EIP-191 message, use the LocalAccount.sign_defunct_message method to produce an eth_account SignableMessage object:

>>> msg = f"It is my permission to spent 1000 SHIB from {local.address.lower()}"
>>> signed = local.sign_defunct_message(msg)
>>> type(signed)
<class 'eth_account.datastructures.SignedMessage'>
>>> signed.messageHash.hex()
'0x2a180b353c317ae903c063141592ec360b25be9f75c60ae16ca19f5578f70a50'

Signing Messages

To sign an EIP712Message, use the LocalAccount.sign_message method to produce an eth_account SignableMessage object:

>>> from eip712.messages import EIP712Message, EIP712Type
>>> local = accounts.add(private_key="0x416b8a7d9290502f5661da81f0cf43893e3d19cb9aea3c426cfb36e8186e9c09")
>>> class TestSubType(EIP712Type):
...     inner: "uint256"
...
>>> class TestMessage(EIP712Message):
...     _name_: "string" = "Brownie Test Message"
...     outer: "uint256"
...     sub: TestSubType
...
>>> msg = TestMessage(outer=1, sub=TestSubType(inner=2))
>>> signed = local.sign_message(msg)
>>> type(signed)
<class 'eth_account.datastructures.SignedMessage'>
>>> signed.messageHash.hex()
'0x2a180b353c317ae903c063141592ec360b25be9f75c60ae16ca19f5578f70a50'

Using a Hardware Wallet

Brownie allows the use of hardware wallets via Clef, an account management tool included within Geth.

To use a hardware wallet in Brownie, start by installing Geth. Once finished, type the following command and follow the on-screen prompts to set of Clef:

clef init

Once Clef is configured, run Brownie in one command prompt and Clef in another. From within Brownie:

>>> accounts.connect_to_clef()

Again, follow the prompts in Clef to unlock the accounts in Brownie. You can now use the unlocked accounts as you would any other account. Note that you will have to authorize each transaction made with a ClefAccount from within clef.