Export deployed contract addresses and store them separately from Truffle artifacts.
Should I commit the build directory?
If you ever worked with Truffle, I bet you asked yourself this question at least once.
There are different currents of thought between developers but there are a few unavoidable side effects in committing the build directory:
- the
updatedAt
field is updated every time a contract is compiled - some user-specific
absolute paths
are stored inside every artifact and may cause problems when multiple persons are working on the same codebase git diffs
become much more difficult and messy to read
But Truffle artifacts also contain the addresses of deployed contracts for each network and these are crucial in order for migrations to work properly.
The solution is to store the addresses in separate files and commit them instead of the build directory.
Later on, another developer working on the same codebase could just clone the repo, compile the contracts and merge the deployment addresses back into the artifacts, thus restoring a clean and working state for Truffle.
npm install --save-dev truffle-deployments
Truffle Deployments works in two stages:
- Export: deployments are read from Truffle artifacts and stored into separate network-specific JSON files.
- Import: previously exported deployments are merged back into Truffle artifacts.
The most common usage is through Command Line Interface but a Programmable API is available as well.
The export command will scan the artifactsDir
and collect info about the deployments that were made on different networks for each contract. Then it will store the deployments in JSON files inside the networksDir
, one for each network.
truffle-deployments export [artifactsDir] [networksDir]
Option | Description |
---|---|
--network <network>, -n |
specify network/s to export (e.g. 1 or 1,4) |
--reset, -r |
delete old exported deployments |
If not specified, artifactsDir
defaults to build/contracts
and
networksDir
defaults to networks
.
If a network file already exists, by default Truffle Deployments will append new deployments without deleting the old ones with the exception of conflicting contracts that will be overwritten. To delete the old deployments consider using the --reset
option.
Consider this initial state:
// build/contracts/Token.json
{
"contractName": "Token",
"abi": [],
"bytecode": "0x60806040523480156200001157600080fd5b50604"
"networks": {
"1": {
"events": {},
"links": {},
"address": "0xefE1e4e13F9ED8399eE8e258b3a1717b7D15f054",
"transactionHash": "0x35db37ae85e2d4af8fb6fc83f1e6edf5ade8700cf75e19dc3f1a0307768948c7"
},
"4": {
"events": {},
"links": {},
"address": "0xb56c770c2fa5222947a9e3c5beb8dc46dd656b5f",
"transactionHash": "0xe31509629b75866917ab387751a75b737b973622d9765af69b557bde038e1210"
}
}
}
Running the export
command will generate the following network files inside the networksDir
:
networks/
1.json
4.json
Each network file contains all exported deployments:
// networks/1.json
[
{
"contract": "Token",
"address": "0xefE1e4e13F9ED8399eE8e258b3a1717b7D15f054",
"transactionHash": "0x35db37ae85e2d4af8fb6fc83f1e6edf5ade8700cf75e19dc3f1a0307768948c7"
}
]
// networks/4.json
[
{
"contract": "Token",
"address": "0xb56c770c2fa5222947a9e3c5beb8dc46dd656b5f",
"transactionHash": "0xe31509629b75866917ab387751a75b737b973622d9765af69b557bde038e1210"
}
]
The import command will scan all the exported deployments inside the networksDir
and merge them into respective contract artifact in the artifactsDir
.
truffle-deployments import [networksDir] [artifactsDir]
Option | Description |
---|---|
--network <network>, -n |
specify network/s to import (e.g. 1 or 1,4) |
If not specified, artifactsDir
defaults to build/contracts
and
networksDir
defaults to networks
.
Consider this initial state:
// networks/4.json
[
{
"contract": "Token",
"address": "0xb56c770c2fa5222947a9e3c5beb8dc46dd656b5f",
"transactionHash": "0xe31509629b75866917ab387751a75b737b973622d9765af69b557bde038e1210"
}
]
// build/contracts/Token.json
{
"contractName": "Token",
"abi": [],
"bytecode": "0x60806040523480156200001157600080fd5b50604"
"networks": {
"1": {
"events": {},
"links": {},
"address": "0xefE1e4e13F9ED8399eE8e258b3a1717b7D15f054",
"transactionHash": "0x35db37ae85e2d4af8fb6fc83f1e6edf5ade8700cf75e19dc3f1a0307768948c7"
}
}
}
Running the import
command will update build/contracts/Token.json
like this:
// build/contracts/Token.json
{
"contractName": "Token",
"abi": [],
"bytecode": "0x60806040523480156200001157600080fd5b50604"
"networks": {
"1": {
"events": {},
"links": {},
"address": "0xefE1e4e13F9ED8399eE8e258b3a1717b7D15f054",
"transactionHash": "0x35db37ae85e2d4af8fb6fc83f1e6edf5ade8700cf75e19dc3f1a0307768948c7"
},
"4": {
"events": {},
"links": {},
"address": "0xb56c770c2fa5222947a9e3c5beb8dc46dd656b5f",
"transactionHash": "0xe31509629b75866917ab387751a75b737b973622d9765af69b557bde038e1210"
}
}
}
Beside the Command Line Interface, Truffle Deployments can also be used programmatically.
const truffleDeployments = require('truffle-deployments');
const artifactsDir = 'build/contracts';
const networksDir = 'networks';
const options = { networks: [4], reset: true };
truffleDeployments.export(artifactsDir, networksDir, options);
const truffleDeployments = require('truffle-deployments');
const artifactsDir = 'build/contracts';
const networksDir = 'networks';
const options = { networks: [4] };
truffleDeployments.import(networksDir, artifactsDir, options);