Truffle Tricks for Ethereum Development: Dispelling 8 Myths & First Impressions

If you haven’t heard of Truffle, go get it. It’s a tool that makes developing Ethereum projects much easier. When people first interact with Truffle, they think they’re confined to fitting into the structure first provided, having a very rare scope that supports only specific types of projects. I’m here to dispel that myth — and many others — and show you some Truffle tricks you didn’t know were possible.

Myth #1: You must use the folders provided to you in the `app` directory

When you run `truffle init` and you’re given an app directory with “javascripts”, “stylesheets” and “images” within it, you might think you have to use those directories to take advantage of Truffle’s build process. You don’t. You can delete those folders, add new ones, or rename them to your heart’s content. Here’s an example build configuration where files have been renamed (notice no images directory):

Directory structure: 
/app
— pages
— controls
— vendor
App configuration:
{
“build”: {
"app.js": [
"vendor/react.js", // structure is up to you
"controls/button.js",
"pages/page_one.jsx",
"pages/page_two.jsx"
]
},
// ...
}

Myth #2: Dependencies must live in the app directory

Paths are relative to the app directory, but that doesn’t mean dependencies have to live there. Here’s an example where the build process refers to dependencies that exist outside of “app”, allowing you to take advantage of package managers like npm:

{
“build”: {
"app.js": [
"../node_modules/jquery/dist/jquery.min.js",
// ...
]
},
// ...
}

Myth #3: Truffle can only build web apps

False. Here’s a great example of Truffle building a library, creating both a distributable and minified version.

Myth #4: Truffle can’t have multiple dependent build targets

Oh but it can. Taken from the same example as Myth #3, you can use build targets as they’re created, since each build target within app.json is created in order:

{
“build”: {
// The main library file.
“hooked-web3-provider.js”: “hooked-web3-provider.es6”,
    // Note, the first one will be processed before this one, 
// so we can refer to the built file.
“hooked-web3-provider.min.js”: {
“files”: [
“../build/hooked-web3-provider.js”
],
“post-process”: [
“uglify”
]
}
},
// ...
}

Myth #5: Like it or not, you must use Truffle’s build process

Nope — this is perhaps the biggest myth. Just delete the “build” configuration from your app.json if you need something more complex (or don’t want a build process at all). You can still use Truffle for contract compilation, testing and deployment.

Myth #6: Contract code requires lots of copy pasta

This isn’t so much a myth it is a lesser-known feature we added to Truffle. Solidity’s import statement leaves much to be desired, so we wrote our own. If you want to include one contract as a dependency of another, simply import it in the order you want it included; Truffle will take care of the rest.

import "Permissioned"; // Looks for ./contracts/Permissioned.sol
contract MyContract is Permissioned {
// ..
}

You can even import nested contract files:

import "tools/Hammer"; // Looks for ./contracts/tools/Hammer.sol

And viola! Mangeable, maintainable code separation, sans pasta.

Myth #7: Truffle doesn’t support different blockchains like development vs. staging vs. production, or a testnet vs. Olympic vs. Frontier)

Au contraire. Truffle has the concept of environments — pulled from Rails — that you can use to configure different blockchains and contracts deployed to those blockchains. By default you’re given development, staging, production and test, but they’re not required. If you don’t need one, just delete it and Truffle will respond accordingly. If you want to make your environments more tailored to you, then rename them. Here’s an example file structure with environment names tailored to the context the app will be deployed to:

Directory structure:
/config
— development
— consensys-testnet
— ethereum-mainnet
- app.json

Each of the directories within `config` should contain a `config.json` file that at minimum defines the network they connect to. You can also use this config file to overwrite the default configuration of any value within `app.json`:

{
"rpc": {
"host": "xx.xx.xx.xx",
"port": "1234"
}
}

Once in place, you can build your application as well as compile and deploy your contracts to use the environments you’ve specified:

// Both compile and deploy will write a contracts.json file to the
// environment specified:
$ truffle compile -e consensys-testnet 
$ truffle deploy -e consensys-testnet
// Building will hook up the contracts in the specified environment
// to the frontend for use. If you keep the production environment,
// `truffle dist` will create a `dist` folder you can commit to
// your respository.
$ truffle build -e consensys-testnet
$ truffle dist

Myth #8: Truffle doesn’t support complex deployment processes

Truffle hasn’t taken a stance on the ideal contract deployment process, so you won’t see any advanced deployment options if you take a deep dive into the code. But complex deployment processes are possible, and can easily be scripted with `truffle exec`. Truffle’s `exec` command lets you run a Node script within the environment you specify (details below), interacting with your contracts the same way you would when writing your frontend or your tests.

Here’s an example script that can be run after `truffle deploy` that hooks up an AppStore contract with an AppFactory:

File Name: register_factories.js
-----------------------------------------------------
var store = AppStore.at(AppStore.deployed_address);
store.registerFactory(“app”, AppFactory.deployed_address)
.then(function(tx) {
console.log(“Registered AppFactory successfully.”);
process.exit(0)
}).catch(function(e) {
console.log(e);
process.exit(1);
});

To run this script, simply run the following. In this example, `truffle exec` will use the contracts that were already deployed to the “consensys-testnet” environment created above:

$ truffle exec ./register_factories.js -e consensys-testnet

Fin.

Truffle is still being actively developed, and has a ways to go before it solves all development and deployment problems in the young Ethereum Frontier. However, through the tricks above we hope you can get one step closer to a manageable, maintainable project. Your feedback is most welcome, and feel free to express any issues, feedback and feature requests in our Gitter as well as the Github issue tracker. Cheers, and happy developing!