npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

truffle-deploy-registry

v0.5.1

Published

Store deployed contract addresses separately from Truffle artifacts.

Downloads

3,332

Readme

Coverage Status Build Status

Store deployed contract addresses separately from Truffle artifacts, and merge the addresses into artifacts.

This module is a complete re-write (with comprehensive tests!) of truffle-migrate-off-chain

Motivation

Truffle is a fantastic tool for creating and deploying smart contracts. We needed a way to commit deployed contract addresses as part of the repository without committing the Truffle artifacts, as they contain paths specific to each developer's filesystem.

Having the addresses separated by network allows us to ignore the local environment but commit the testnet and mainnet environments to the repository. Our continuous deployment server can then re-compile the artifacts and use the apply-registry command to merge in the deployed (Ropsten, Mainnet, etc.) addresses.

Install

$ npm install --save-dev truffle-deploy-registry

or

$ yarn add truffle-deploy-registry -D

Configuration

If you are using this library via JS (instead of via the command line) you can configure the networks, input

| Command | Description | | --- | --- | | setNetworksPath(path) | Sets a new networks path (ie. 'networks-two') | | getNetworksPath() | Returns the configured networks path (or the default networks path) |

Example of using a different path for network configs:

var tdr = require('truffle-deploy-registry')
tdr.config.setNetworksPath('networks-two')

const networkId = 3 // ropsten
const contractName = 'SimpleToken'

// Will search the ./networks-two directory for a file called 3.json, and if there
// are multiple contract addresses listed for 'SimpleToken' it will return the most
// recent address. (Networks files are sorted chronologically)
const mostRecentAddress = findLastByContractName(networkId, contractName)

// Example return:
// {
//   "contractName": "SimpleToken",
//   "address": "0x8f0483125fcb9aaaefa9209d8e9d7b9c8b9fb90f",
// }

You can also configure the input and output artifacts path via the config object, however those settings currently only affect the command line.

The apply-registry CLI Tool

After Truffle compiles your smart contracts you can merge the deployed addresses into the artifacts by calling apply-registry from the terminal:

$ apply-registry

By default, apply-registry will use the truffle artifact directory './build/contracts' and the network config directory './networks'.

Customizing apply-registry Using Options

You can configure the input-artifacts, output-artifacts and networks directories which apply-registry uses via the command line options. For example:

$ apply-registry -i build/contracts -o build/output -n networks

In this case, merged artifacts would appear in build/output instead of build/contracts.

Usage

Truffle Deploy Registry works in two stages:

  1. New deployment entries are recorded in a network-specific JSON file.
  2. The latest deployment entries are merged with the truffle artifacts after compilation.

1. Network files

Truffle Deploy Registry stores contract addresses in JSON files in the networks/ directory. For example, if you deploy to mainnet and ropsten your networks directory may look like:

networks/
  1.json
  3.json

Each of these files contains an array of deployment entries. New entries are appended. Each entry must store the contractName and address, but is otherwise unstructured so that the user can add additional information. A network config looks something like:

# networks/1.json
[
  { contractName: 'Ownable', address: '0x3383c29542b8c96eafed98c4aafe789ddb256e19', transactionHash: '0x0b71a01c6da8e02359b533f16b97a590be8ca59480151ba1034a264a2981261f' },
  { contractName: 'Registry', address: '0x8fa5944b15c1ab5db6bcfb0c888bdc6b242f0fa6', transactionHash: '0x84a9fe87a9fd8f7ae98fa72359b533f16b97a590be8ca59480151ba1034a2632' }
]

To add new entries call the appendInstance function:

// migrations/1_initial_migration.js

var tdr = require('truffle-deploy-registry')
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer, network) {
  deployer.deploy(Migrations).then((migrationsInstance) => {
    if (!tdr.isDryRunNetworkName(network)) {
      return tdr.appendInstance(migrationsInstance)
    }
  })
}

Alternatively, you can use the lower-level append function:

// migrations/1_initial_migration.js

var tdr = require('truffle-deploy-registry')
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer, network) {
  deployer.deploy(Migrations).then(async (migrationsInstance) => {
    if (!tdr.isDryRunNetworkName(network)) {
      await tdr.append(deployer.network_id, {
        contractName: 'Migrations',
        address: Migrations.address,
        transactionHash: migrationsInstance.transactionHash
      })  
    }
  })
}

Note the use of isDryRunNetworkName to prevent appending to the registry when doing a dry run.

2. Merging network addresses into artifacts

After Truffle compiles your smart contracts, you can merge the deployed addresses into the artifacts by calling apply-registry from the terminal:

$ apply-registry

NOTE: By default, apply-registry will use the truffle artifact directory './build/contracts' and the network config directory './networks'. If you need to customize this see apply-registry options

This will pull in all of the network configs and add the most recent address for each contract by name from each configuration. For example, if you have two configs:

networks/
  1.json
  3.json

1.json:

[
  { "contractName": "Contract2", "address": "0x2222222222222222222222222222222222222222", "transactionHash": "0x0b71a01c6da8e02359b533f16b97a590be8ca59480151ba1034a264a2981261f" },
  { "contractName": "Contract2", "address": "0x4444444444444444444444444444444444444444", "transactionHash": "0x21afe897aefa98eaf79ae6f87ae6f87678e6f39480151ba1034a264a29853124"  },
]

3.json:

[
  { "contractName": "Contract2", "address": "0x8888888888888888888888888888888888888888", "transactionHash": "0x99afe897aefa98eaf79ae6f87ae6f87678e6f39480151ba1034a264a29853124" }
]

build/contracts/Contract2.json:

{
  "contractName": "Contract2",
  "abi": [],
  "networks": {
    "2": {
      "events": {},
      "links": {},
      "address": "0x3383c29542b8c96eafed98c4aafe789ddb256e19",
      "transactionHash": "0xbef1787981c4512c8bc8acf59e6cbe9c23c9c5ea269b193ec71aae9f9c57c997"
    }
  },
  "updatedAt": "2018-09-19T21:37:52.903Z"
}

Then run apply-registry:

$ apply-registry

Your artifact build/contracts/Contract2.json will now be updated with the networks:

{
  "contractName": "Contract2",
  "abi": [],
  "networks": {
    "1": {
      "events": {},
      "links": {},
      "address": "0x4444444444444444444444444444444444444444",
      "transactionHash": "0x21afe897aefa98eaf79ae6f87ae6f87678e6f39480151ba1034a264a29853124"
    },
    "2": {
      "events": {},
      "links": {},
      "address": "0x3383c29542b8c96eafed98c4aafe789ddb256e19",
      "transactionHash": "0xbef1787981c4512c8bc8acf59e6cbe9c23c9c5ea269b193ec71aae9f9c57c997"
    },
    "3": {
      "events": {},
      "links": {},
      "address": "0x8888888888888888888888888888888888888888",
      "transactionHash": "0x99afe897aefa98eaf79ae6f87ae6f87678e6f39480151ba1034a264a29853124"
    },
  },
  "updatedAt": "2018-09-19T21:37:52.903Z"
}

It can help to create a new script entry in package.json so that you can easily combine compilation with merging:

{
  "scripts": {
    "compile": "truffle compile && apply-registry"
  }
}
Another Use Case

Some of our contract projects use ZeppelinOS. While ZOS has many upsides (easily upgradeable contracts being a huge one, guards against destroying deployed memory addresses, etc) we've found the need to manually copy over contract addresses both in development and on testnets/mainnet.

The apply-registry tool will generate new artifacts in the output artifacts directory even if there are no input artifacts. The workflow for this is as follows:

  1. Deploy contracts using ZOS to local ganache, ropsten, etc.

  2. Manually copy the deployed contract names and addresses to a new networks file in our dapp directory. For instance, the networks file: ./networks/3.json would have entries as such (where the lowest entry address '0xae399886...' is the most recent deployed version):

[
  {
    "contractName": "SimpleToken",
    "address": "0x8f0483125fcb9aaaefa9209d8e9d7b9c8b9fb90f"
  },
  {
    "contractName": "SimpleToken",
    "address": "0xae39986e9876c91a936adfae8b6a98e764aeeb7a"
  }
]
  1. Run apply-registry and it will generate the SimpleToken.json artifact in './build/contracts', ready for the dapp to use.
  2. To get the ABI, use npm or yarn's link command. Or, if the contracts are published on npm simply add the contracts package to your package.json and install.

3. Retrieving Entries

You can retrieve the last entry by contract name using the findLastByContractName(networkId, contractName) function.

For example:

const TestContract = artifacts.require('TestContract.sol')
const tdr = require('truffle-deploy-registry')

module.exports = function(deployer, networkName) {
  deployer.then(async () => {
    const entry = await tdr.findLastByContractName(deployer.network_id, 'Contract2')
    deployer.deploy(TestContract, entry.address).then(instance => {
      if (!tdr.isDryRunNetworkName(networkName)) {
        await tdr.appendInstance(instance)
      }
    })
  })
}

Future Work

Eventually it would be best to create entirely separate artifacts that include the bytecode and abi, rather than having to merge into the compiled artifact. Another possibility is to integrate with EthPM and treat each deployment as a package.