šļø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:
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:
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:
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:
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:
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