I recently built a Dapp in only 1 day for a demo. It’s called the Crypto Museum and allows users to upload artwork as ERC-721 tokens.
The work included writing smart contracts, deploying them, creating a Frontend, interacting with the contracts through Metamask and deploying said Frontend to share it with the world.
The Dapp is a bit rough around the edges. It could have been more visually pleasing for sure.
But it works, and it was done in just 1 day.
Whether it is for a demo, to build up your personal portfolio, for a hackathon, just for fun or for your personal development, you will find a lot of value grabbing a seat by the fire and spending the next few minutes with me.
It’s worth mentioning that this is not the first Dapp I’ve ever developed, which explains in part how I got the app up and running so quickly. If it’s your first time writing a Dapp, treat it as a learning opportunity. That being said, the main reason I made it so fast boils down to using good tools and frameworks.
In the next few minutes, I’ll show you how to rock Dapp development. We’ll learn tips, tricks and the best stack for the job.
Have a Rough Idea Before Starting
Here’s a trick that will save you tons of time: have a rough idea of what your Dapp will look like before starting.
Either have a clear visual image in your head or draw what it will look like on a piece of paper. Make a list of the important functionalities you want to include.
For the Crypto Museum dapp, I already had a clear Idea of what I wanted the app to do. I wanted a token creation flow with instructions on how to generate new instances of ERC-721 tokens from uploaded images. From that, I knew I had to write an ERC-721 contract and deploy it.
Having at least a rough idea of what you want to accomplish beforehand will allow you to work more effectively and help you determine which tools to use right off the bat.
Speaking of tools…
The Truffle Suite with a Truffle Box
The Truffle Suite is set of of several tools for Dapp development.
As a Dapp developer, you need to git gud with the Truffle Suite.
Below are some of its core components, all of which I’ve used extensively myself.
Drizzle: Gives you awesome React Components for querying your smart contracts alongside of a redux-based state manager that keeps your blockchain data up-to-date by listening to your web3 provider. And it integrates really well with…
Truffle: Truffle manages your smart contract deployments and abi. It is a useful tool for quickly iterating when writing smart contracts and keeping your web3 artifacts updated.
Ganache: This neat tool allows you to spin a locally-running instance of an Ethereum blockchain on which you can deploy your contracts. No need to wait for transaction confirmation. No need to get test ether from faucets. It goes well with Truffle.
So the Suite is Drizzle + Truffle + Ganache… That sounds like a lot of stuff to setup.
Luckily, Truffle supports so-called Truffle boxes. Truffle Boxes set up all the boilerplate for you and come with a simple example Dapp that you can modify as you see fit.
I highly recommend the Drizzle box. You can install it via npx.
npx truffle unbox drizzle
This wil setup React and the entire Truffle Suite for you. Oh my!
Writing the Smart Contracts: Start With Open Zepelin
When writing smart contracts, don’t reinvent the wheel. All I needed was an ERC-721 smart contract with some additional functions. ERC-721 smart contracts have been standardized and perfected already.
Use the Open Zepellin smart contracts for standard boilerplate code and make any modification on top of them. Seriously, it’s high-quality audited code. Don’t waste your time re-writing simple ERC-20/ERC-721 contracts in which you might introduce errors by mistake.
For example, here’s the ERC-721 contract for Crypto Museum. It allows users to mint new tokens and attach an IPFS hash(CID).
pragma solidity >=0.5.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract CryptoMuseum is ERC721 {
constructor() ERC721("CryptoMuseum", "CM") public {
}
mapping(uint256 => string) private _CIDS;
function CID(uint256 tokenId) public view returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: CID query for nonexistent token");
string memory _CID = _CIDS[tokenId];
return _CID;
}
function _setTokenCID(uint256 tokenId, string memory _CID) internal virtual {
require(_exists(tokenId), "ERC721Metadata: CID set of nonexistent token");
_CIDS[tokenId] = _CID;
}
function mint(string memory _CID) public {
uint256 _newId = totalSupply() + 1;
_safeMint(msg.sender, _newId);
_setTokenCID(_newId, _CID);
}
}
Deploy the Contracts
For contract deployment, create an Infura account, generate an api key and save it as an environment variable. Do the same thing for a mnemonic seed for your wallet. For example, on Linux I added the following line to ~/.bashrc
:
export MNEMONIC_ROPSTEN="bla bla bla"
export INFURA_ACCESS_KEY="1234"
The mnemonic can be generated here: https://iancoleman.io/bip39. Also, take note of the Ethereum address that goes with that mnemonic so you can send ether to cover the gas for contract deployment.
Make truffle.config.js
look like this:
const path = require("path");
const HDWalletProvider = require("truffle-hdwallet-provider");
const mnemonic = process.env.MNEMONIC_ROPSTEN;
const infuraAccessKey = process.env.INFURA_ACCESS_KEY
module.exports = {
contracts_build_directory: path.join(__dirname, "app/src/contracts"),
networks: {
develop: { // default with truffle unbox is 7545, but we can use develop to test changes, ex. truffle migrate --network develop
host: "127.0.0.1",
port: 7545,
network_id: "5777"
},
ropsten: {
network_id: "3",
provider: () => {
return new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/${infuraAccessKey}`);
},
}
},
compilers: {
solc: {
version: "0.6.2",
},
},
plugins: [
'truffle-plugin-verify'
],
api_keys: {
etherscan: process.env.ETHERSCAN_API_KEY
}
};
Verify the Contracts of Etherscan
This step is optional, but you probably want to have your contracts verified on Etherscan, right?
Use the truffle-plugin-verify npm package to automatically verify your contracts on Etherscan.
Alternatively, if you want to do things manually, you can install a smart contract flattener, which will import all your Open Zeppelin dependencies into one contract which you can then upload on Etherscan.
npm install truffle-flattener -g
truffle-flattener ./contract/MyContract.sol
Deploy Your App
Full disclosure here. The next tool is developed by the company I work for. However, I genuinely think it is the best way to get your Dapp on the internet. Oh, and it also uses with IPFS!
It’s called Fleek, a tool for web hosting compatible with any framework, including React applications.
It deploys React apps very easily so there’s no need to waste time with web hosting. Also, you get a free domain ending with .on.fleek.co
which you can change to your liking. Finally, once set up, Fleek will automatically re-build your Dapp and deploy it when a change is made to the github repo containing it.
Good Dapp Development!!
So to recap the stack I recommend for dapp development is Drizzle, Truffle and React bundled in a Truffle Box, Open Zepelin as a starting point for the smart contracts if possible, Infura for deployment, Fleek for deploying the Dapp.
The tooling for Dapp development on Ethereum is amazing. That’s why a dapp can be developed so fast. I invite you to experiment and create all kinds of Dapps. Let your imagination wild!
I promise you, you will have a ton of fun doing so.
Come back next week to learn more about specific technologies of the stack I suggested!