🗜️Clevis + 📃 Dapparatus = 🔗🔥

Zero to Dapp, ASAP 😜

Clevis and Dappartus are my custom tools to build dapps as fast as possible. They help orchestrate the deployment of my smart contracts and provide quick access to commonly used components in React. I will dive into my process step-by-step from provisioning a server to mainnet deployment in the following article and then do a screencast that demonstrates the actions live:


If you want to run Clevis locally, you can skip all the provisioning steps below, but don’t forget to launch ganache-cli so you have a local Ethereum node.

Let’s start from nothing and fire up a fresh AWS EC2 instance from Ubuntu:

I’ll spin up a t2.small box which costs around $16 a month, but once the AMI is ready in AWS it could probably be scaled all the way down to a t2.nano.

We’ll need to open a few ports in a new security group too:

Port 22 (SSH) 
Port 30303 (Geth)
Port 3000 (Http/React)
Be sure port 8545 is blocked to outside traffic! This will be an open RPC port!

To make SSHing easier, I’ll add an entry to my ~/.ssh/config

Host rinkeby
User ubuntu
Port 22
Hostname 18.191.175.177
IdentityFile ~/.ssh/MYKEYNAME.pem
TCPKeepAlive yes
ForwardAgent yes
IdentitiesOnly yes
StrictHostKeyChecking no

Now, with the box spun up, I can just ssh rinkeby and I’m in!

Let’s provision the box…

sudo apt-get update 
sudo apt-get dist-upgrade -y
sudo apt-get upgrade -y
sudo apt-get install build-essential python htop -y
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update && sudo apt-get install ethereum -y

Now let’s setup the rc.local so it syncs with the blockchain on boot…

Create a file called rc.local in your home directory with the contents:

#!/bin/sh -e
/usr/bin/geth version > /home/ubuntu/geth.log 2>&1
/usr/bin/geth --rinkeby --syncmode "light" --cache 512 --maxpeers 25 --datadir "/home/ubuntu/.geth" --rpc --rpcapi="db,eth,net,web3,personal" > /home/ubuntu/geth.log 2>&1 &
exit 0

(Note: replace — rinkeby with your chain of choice, remove for mainnet)

Then link that file over the top of the current rc.local and reboot:

sudo rm /etc/rc.local
sudo ln -s /home/ubuntu/rc.local /etc/rc.local
sudo chmod +x /etc/rc.local
sudo reboot

Now when the machine comes up and we ssh in, it should be syncing:

It will take a while before it really gets going and syncs up.
Once it starts getting blocks one at a time you are in sync and ready to go.
NPM has some troubles with global installs as the Ubuntu user so you can move global installs to be local to the user’s directory. This is probably different on your machine and I would start by simply installing clevis with -g
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATH
source ~/.profile
echo "export PATH=~/.npm-global/bin:\$PATH" >> .bashrc

Now let’s install clevis as a global bin:

npm install -g clevis

Now that clevis is a command we should be able to run from anywhere. Let’s create a new project starting with an empty git repo and build a simple Dapp.

cd ~
git clone https://github.com/austintgriffith/broadcaster-example-dapp.git
cd broadcaster-example-dapp
clevis init
npm start

This should bring up a webserver and if you navigate to the ip on port 3000 in a browser you’ll get a Dapp scaffolding up and ready:

Okay so technically we have a “Dapp”, but let’s actually #BUIDL something. Leave the development server up and running and create a new SSH session:

ssh rinkeby
cd ~/broadcaster-example-dapp
clevis create Broadcaster

This will create a blank smart contract that we can fill in with a few functions:

pragma solidity ^0.4.24;
contract Broadcaster {
  constructor() public {
emit Broadcast(now,"Contract Created!");
}
  function broadcast(string output) public returns (bool){
emit Broadcast(now,output);
return true;
}
  event Broadcast(uint timestamp, string output);
}

Now let’s compile and deploy the contract using Clevis:

clevis compile Broadcaster

Okay, time to interface with the blockchain… once geth is in sync, we’ll want to create some accounts.

> clevis accounts
[]
> clevis new ""
> clevis balance 0
{ ether: '0', wei: '0', usd: 0 }

We have an account on the machine that can be used to deploy things, but first I’ll need to charge it up with some Eth:

> clevis balance 0
300000000000000000
> clevis unlock 0 ""
true

With our contract already compiled, we can now deploy it using account 0:

cd ~/broadcaster-example-dapp
clevis deploy Broadcaster 0

Compiling and deploying creates a few files of interest:

The Broadcaster.compiled is the file you upload to Etherscan to verify the source code. It will include all imports, etc:

Let’s interact with the contract first from the command line to make sure it performs like we think it will. We can use the Clevis explain command to see the contract’s interface:

Next, we can use the Clevis contract command to interact with the contract:

clevis contract broadcast Broadcaster 0 "Hello World"

This is telling clevis to run the broadcast command on the Broadcaster smart contract as account 0 with the arguments “Hello World”:

And we can test that our transaction worked by listing the events:

clevis contract eventBroadcast Broadcaster

Let’s go ahead and write a test to make sure that after we deploy a contract we can run the broadcast function and it will create an event with the correct string as the output.

Notice that the javascript in the test command looks exactly like our command line tests. This is an important part of Clevis. You can run things from the command line just to get a feel for them and then do the exact same thing in a mocha test when you are ready.

Now let’s run our test:

clevis test broadcast

Awesome. So our contract is written, compiled, deployed, and tested. The cool thing about Clevis tests is they are actually part of the overall orchestration; they do a lot of important actions. For instance, I could compile, test, deploy, and publish simply with clevis test full. See the tests/ directory to learn more about clevis testing and mocha.

Now let’s inject our contract into our Dapp and start interfacing with it from the React frontend code:

clevis test publish

Now we have published our contract which injects it into our Dapp:

Clevis injects important contract files like the abi, address, etc into the React app.

Now it’s time to bring in some Dapparatus components:

First, let’s throw the Contract Loader into the connectedDisplay:

Then, let’s fire up our React development server and see what we have so far.

cd ~/broadcaster-example-dapp
npm start

Navigate to the machine’s IP on port 3000:

http://18.191.175.177:3000/

Let’s dive into the console and look at what those components give us back:

MetaMask component keeps your state up-to-date with account, balance, block, network, etc.
Gas component keeps your state up-to-date with current gas prices.
ContractLoader component creates a “contracts” object in the React state to interface with the contracts.

We are connected to the Ethereum network, we know the current gas prices, and we have our contract interface ready to go. Rad.

To make transactions we will need to bring in the Transactions component:

Transactions component creates a tx() function for making transactions.

The Transactions component also creates a display in the bottom right that shows blocks and transactions loading with progress bars

Now let’s bring in a few more components for the user interface:

Address component and Button component for a nice little UI

Now let’s wire our button up to call the broadcast function on our Broadcaster smart contract just like we did in our tests:

We can fill in a broadcast string, hit Send, sign the transaction, and it’s off to the blockchain. Now that we are sending transactions to our contract, let’s bring in an “Events” component to track the events:

We’re almost done! Let’s see how this thing looks on a mobile sized window:

Oh, that’s no good. Call in the Scaler component to help us render our UI in a way that shrinks to smaller screens! To do this, wrap your UI elements with a <Scaler> </Scaler> and it will dynamically handle the scaling.

At this point of my Clevis build, I would usually move to a mainnet box and deploy to the main Ethereum chain, but I’ll skip that. Once my contracts are live, I deploy my React site up to S3 and put it behind Cloudfront for caching:

clevis build
clevis upload mysite.io
clevis invalidate CLOUDFRONTID

For more information on this process, check out my NiftiesVsNfties hack:

Thank you for checking out Clevis:

Go yell at me on Twitter: https://twitter.com/austingriffith

Learn more about me at: https://austingriffith.com