Configuration¶
Introduction¶
Populus is designed to be highly configurable through the configuration files.
By default, populus will load the configuration from two files: the user-scope main config file
at ~/.populus/config.json
, and the project-scope config file, at the project directory,
project.json
.
Both files share the same JSON schema. You should use the project.json
file for local changes that
apply to specific project,
and the user-scope file for the environment configs, which apply to all your projects.
When a configuration key exists in both the user-config and the project-config, the project-config overrides the user-config. However, progrmatically you have access to both configs and can decide in runtime to choose otherwise.
The $ populus init
command writes a minimal project.json
default file to the project directory.
Note
The project.json
file is required, and all the populus commands require a directory with a project config file.
A Note for Django users¶
If you are used to django’s settings.py
file, populus is quite different.
The configuration is saved in JSON files, on purpuse.
While saving the configuration in a Python module is convinient, and often looks nicer, there is a caveat: a python module is after all
a programmble, running code. With an Ethereum development platform, that deals directly with money, we think
it’s safer to put the configurations in static, non programmble, and external files.
The option to change the configuration dynamically is still available in run time, using the project.config
propery.
But otherwise, Populus configuration comes from static JSON files. What you see is what you get, no surprises.
What You Can Configure¶
This config file controls many aspects of populus that are configurable. Currently the config file controls the following things.
- Project root directory
- Contract source file location
- Compiler settings
- Available chains and how web3 connects to them.
Compiler Configuration¶
Each complication backend takes settings that are passed down to Solidity compiler Input Description (JSON) and command line.
Here is an example for the compilation backend settings when using
contract source files in folders outside of the Populus default ./contracts
folder.
{
"compilation": {
"contracts_source_dirs": [
"./contracts",
"/path-to-your-external-solidity-files",
],
"backend": {
"class": "populus.compilation.backends.SolcCombinedJSONBackend",
"settings": {
"stdin": {
"optimizer": {
"enabled": true,
"runs": 500
},
"outputSelection": {
"*": {
"*": [
"abi",
"metadata",
"evm.bytecode",
"evm.deployedBytecode"
]
}
}
},
"command_line_options": {
"allow_paths": "/path-to-your-external-solidity-files"
}
}
}
}
}
}
backend.settings
has two keys
stdin
is Solidity Input Description as JSONcommand_line_options
are passed to Solidity compiler command line, as given keyword arguments to py-solc package’s solc.wrapper.solc_wrapper <https://github.com/ethereum/py-solc/blob/3a6de359dc31375df46418e6ffd7f45ab9567287/solc/wrapper.py#L20>_
Contract Source Directory¶
The directory that project source files can be found in.
- key:
compilation.contracts_source_dirs
- value: List of filesystem paths
- default:
['./contracts']
Compiler Backend¶
Set which compiler backend should be used
- key:
compilation.backend.class
- value: Dot separated python path
- default:
populus.compilation.backends.SolcStandardJSONBackend
Settings for the compiler backend
- key:
compilation.backend.settings
- value: Object of configuration parameters for the compiler backend.
- default:
{"optimize": true, "output_values": ["abi", "bin", "bin-runtime", "devdoc", "metadata", "userdoc"]}
Configuring compiler for extra¶
Set solc import path remappings. This is especially useful if you want to use libraries like OpenZeppelin with your project. Then you can directly import Zeppelin contracts like import "zeppelin/contracts/token/TransferableToken.sol";
.
- key:
compilation.import_remappings
- value: Array of strings
- default:
[]
- example:
["zeppelin=zeppelin"]
assuming that the root directory for the Zeppelin contracts is./zeppelin
in the root of your project.
Chains¶
The chains
key within the configuration file declares what chains populus
has access to, and how to connect to them. Populus comes pre-configured with
the following chains.
'mainnet'
: Connects to the public ethereum mainnet viageth
.'ropsten'
: Connects to the public ethereum ropsten testnet viageth
.'tester'
: Uses an ephemeral in-memory chain backed by pyethereum.'testrpc'
: Uses an ephemeral in-memory chain backed by pyethereum.'temp'
: Local private chain whos data directory is removed when the chain is shutdown. Runs viageth
.
{
"chains": {
"my-chain": {
... // The chain settings.
}
}
}
Individual Chain Settings¶
Each key and value in the chains
portion of the configuration corresponds
to the name of the chain and the settings for that chain. Each chain has three
primary sections, web3
, chain
, and contracts
configuration settings.
{
"chains": {
"my-chain": {
"chain": {
"class": "populus.chain.LocalGethChain"
},
"web3": {
"provider": {
"class": "web3.providers.ipc.IPCProvider"
}
},
"contracts": {
"backends": {
"JSONFile": {"$ref": "contracts.backends.JSONFile"},
"ProjectContracts": {
"$ref": "contracts.backends.ProjectContracts"
}
}
}
}
}
}
The above chain configuration sets up a new local private chain within your
project. The chain above would set it’s data directory to
<project-dir>/chains/my-chain/
.
To simplify configuration of chains you can use the ChainConfig
object.
>>> from populus.config import ChainConfig
>>> chain_config = ChainConfig()
>>> chain_config.set_chain_class('local')
>>> chain_config['web3'] = web3_config # see below for the Web3Config object
>>> project.config['chains.my-chain'] = chain_config
The set_chain_class()
method can take any of the following values.
- These strings
chain_config.set_chain_class('local') => 'populus.chain.LocalGethChain'
chain_config.set_chain_class('external') => 'populus.chain.ExternalChain'
chain_config.set_chain_class('tester') => 'populus.chain.TesterChain'
chain_config.set_chain_class('testrpc') => 'populus.chain.TestRPCChain'
chain_config.set_chain_class('temp') => 'populus.chain.TemporaryGethChain'
chain_config.set_chain_class('mainnet') => 'populus.chain.MainnetChain'
chain_config.set_chain_class('testnet') => 'populus.chain.TestnetChain'
chain_config.set_chain_class('ropsten') => 'populus.chain.TestnetChain'
- Full python paths to the desired chain class.
chain_config.set_chain_class('populus.chain.LocalGethChain') => 'populus.chain.LocalGethChain'
chain_config.set_chain_class('populus.chain.ExternalChain') => 'populus.chain.ExternalChain'
...
- The actual chain class.
chain_config.set_chain_class(LocalGethChain) => 'populus.chain.LocalGethChain'
chain_config.set_chain_class(ExternalChain) => 'populus.chain.ExternalChain'
...
Chain Class Settings¶
Determines which chain class will be used for the chain.
- key:
chains.<chain-name>.chain.class
- value: Dot separated python path to the chain class that should be used.
- required: Yes
Available options are:
populus.chain.ExternalChain
A chain that populus does not manage or run. This is the correct class to use when connecting to a node that is already running.
populus.chain.TestRPCChain
An ephemeral chain that uses the python
eth-testrpc
package to run an in-memory ethereum blockchain. This chain will spin up an HTTP based RPC server.populus.chain.TesterChain
An ephemeral chain that uses the python
eth-testrpc
package to run an in-memory ethereum blockchain. This chain must be used in conjunction with a web configuration using the providerEthereumTesterProvider
.populus.chain.LocalGethChain
A geth backed chain which will setup it’s own data directory in the
./chains
directory in the root of your project.populus.chain.TemporaryGethChain
An ephemeral chain backed by
geth
which uses a temporary directory as the data directory which is removed when the chain is shutdown.populus.chain.TestnetChain
A
geth
backed chain which connects to the public Ropsten test network.populus.chain.MainnetChain
A
geth
backed chain which connects to the main public network.
Custom Chains Using the ExternalChain Class¶
You can define your own custom chains. Custom chains should use the ExternalChain
class,
which lets you access a Web3 provider. Web3 is the actual layer that connects to the running geth process,
and let Populus interact with the blockchain.
Note
If you are familiar with web development, then you can think of Web3 as the underlying WSGI. In web development WSGI hooks to Apache or Nginx, here we have Web3 that hooks to geth.
The minimum configuration that Web3 requires are either:
IPCProvider
: connects to geth via IPC, by the configuredipc_path
HTTPProvider
: connects via http or https to geth’s rpc, by the configuredendpoint_uri
Here are two examples of a custom ExternalChain
configuration.
IPC
"chains": {
"horton": {
"chain": {
"class": "populus.chain.ExternalChain"
},
"web3": {
"provider": {
"class": "web3.providers.ipc.IPCProvider",
"settings": {
"ipc_path": "./chains/horton/geth.ipc"
}
}
},
...
}
}
HTTP
"chains": {
"local_chain": {
"chain": {
"class": "populus.chain.ExternalChain"
},
"web3": {
"provider": {
"class": "web3.providers.rpc.HTTPProvider",
"settings": {
"endpoint_uri": "https://127.0.0.1:8545"
}
}
},
...
}
}
The important thing to remeber is that Populus will not run geth for you. You will
have to run geth, and then Populus will use the chain configuration to connect to this already running process via Web3.
If you created a local chain with the $ populus chain new
command, Populus will create an executable that you
can use to run the chain, see Running the Local Blockchain
In the next Populus version, all the chains will be configured as ExternalChain
For more details on Web3, see the Web3 documentation .
Web3 Configuration¶
Configuration for setting up a Web3 instance.
{
"provider": {
"class": "web3.providers.ipc.IPCProvider",
"settings": {
"ipc_path": "/path/to/geth.ipc"
}
}
"eth": {
"default_account": "0xd3cda913deb6f67967b99d67acdfa1712c293601",
}
}
In order to simplify configuring Web3 instances you can use the Web3Config
class.
>>> from populus.config import Web3Config
>>> web3_config = Web3Config()
>>> web3_config.set_provider('ipc')
>>> web3_config.provider_kwargs['ipc_path'] = '/path/to/geth.ipc'
>>> web3.config.default_account = '0x0000000000000000000000000000000000000001'
>>> project.config['chains.my-chain.web3'] = web3_config
>>> project.write_config() # optionally persist the configuration to disk
Provider Class¶
Specifies the import path for the provider class that should be used.
- key:
provider.class
- value: Dot separated python path
- required: Yes
Provider Settings¶
Specifies the **kwargs
that should be used when instantiating the provider.
- key:
provider.settings
- value: Key/Value mapping
Default Account¶
If present the web3.eth.defaultAccount
will be populated with this address.
- key:
eth.default_account
- value: Ethereum Address
Configuration API¶
The project configuration can be accessed as a property on the Project
object via project.config
. This object is a dictionary-like object with
some added convenience APIs.
Project configuration is represented as a nested key/value mapping.
Getting and Setting¶
The project.config
object exposes the following API for getting and setting
configuration values. Supposing that the project configuration file contained
the following data.
{
'a': {
'b': {
'c': 'd',
'e': 'f'
}
},
'g': {
'h': {
'i': 'j',
'k': 'l'
}
}
}
The config object supports retrieval of values in much the same manner as a dictionary. For convenience, you can also access deep nested values using a single key which is dot-separated combination of all keys.
>>> project.config.get('a')
{
'b': {
'c': 'd',
'e': 'f'
}
}
>>> project.config['a']
{
'b': {
'c': 'd',
'e': 'f'
}
}
>>> project.config.get('a.b')
{
'c': 'd',
'e': 'f'
}
>>> project.config['a.b']
{
'c': 'd',
'e': 'f'
}
>>> project.config.get('a.b.c')
'd'
>>> project.config['a.b.c']
'd'
>>> project.config.get('a.b.x')
None
>>> project.config['a.b.x']
KeyError: 'x'
>>> project.config.get('a.b.x', 'some-default')
'some-default'
The config object also supports setting of values in the same manner.
>>> project.config['m'] = 'n'
>>> project.config
{
'a': {
'b': {
'c': 'd',
'e': 'f'
}
},
'g': {
'h': {
'i': 'j',
'k': 'l'
}
},
'm': 'n'
}
>>> project.config['o.p'] = 'q'
>>> project.config
{
'a': {
'b': {
'c': 'd',
'e': 'f'
}
},
'g': {
'h': {
'i': 'j',
'k': 'l'
}
},
'm': 'n'
'o': {
'p': 'q'
}
}
Config objects support existence queries as well.
>>> 'a' in project.config
True
>>> 'a.b' in project.config
True
>>> 'a.b.c' in project.config
True
>>> 'a.b.x' in project.config
False
Config References¶
Sometimes it is useful to be able to re-use some configuration in multiple
locations in your configuration file. This is where references can be useful.
To reference another part of your configuration use an object with a single key
of $ref
. The value should be the full key path that should be used in
place of the reference object.
{
'a': {
'$ref': 'b.c'
}
'b': {
'c': 'd'
}
}
In the above, the key a
is a reference to the value found under key b.c
>>> project.config['a']
['d']
>>> project.config.get('a')
['d']
Defaults¶
Populus ships with many defaults which can be overridden as you see fit.
Built-in defaults¶
Populus ships with the following default configuration.
{
"version":"7",
"compilation":{
"contracts_source_dirs": ["./contracts"],
"import_remappings": []
}
}
It is recommended to use the $ populus init
command to populate this file
as it contains useful defaults.
Pre-Configured Web3 Connections¶
The following pre-configured configurations are available. To use one of the configurations on a chain it should be referenced like this:
{
"chains": {
"my-custom-chain": {
"web3": {"$ref": "web3.GethIPC"}
}
}
}
InfuraMainnet¶
Web3 connection which will connect to the mainnet ethereum network via Infura.
- key:
web3.InfuraMainnet
InfuraRopsten¶
Web3 connection which will connect to the ropsten ethereum network via Infura.
- key:
web3.InfuraRopsten
Command Line Interface¶
You can manage your configuration using the command line with the $ populus
config
command.
$ populus config
Usage: populus config [OPTIONS] COMMAND [ARGS]...
Manage and run ethereum blockchains.
Options:
-h, --help Show this message and exit.
Commands:
delete Deletes the provided key/value pairs from the...
get Gets the provided key/value pairs from the...
list Prints the project configuration out to the...
set Sets the provided key/value pairs in the...
To interact with nested keys simply separate them with a .
.
$ populus config list
some.nested.key_a: the_value_a
some.nested.key_b: the_value_b
$ populus config set some.nested.key_c:the_value_c
$ populus config list
some.nested.key_a: the_value_a
some.nested.key_b: the_value_b
some.nested.key_c: the_value_c
$ populus config get some.nested.key_a
some.nested.key_a: the_value_a
$ populus config delete some.nested.key_a
some.nested.key_a: the_value_a (deleted)