NOTE: I’m assuming you’re familiar with programming, and programming with JavaScript in particular.

If you’re like me, and you’re getting started with developing on Ethereum, you’re likely struggling to define a learning path. I recently saw someone put it this way:

I have found it very challenging to even know what questions to ask.

I have found developing on Ethereum, and blockchain in general, so new and different, that I have had to invest a significant amount of time just getting acquainted with terminology and understanding the big picture.

After several weeks I am now beginning to feel a little less lost; I have a basic understanding of what it means to develop on Ethereum, as well as what tools and resources are available to me. I’ve put together a brief outline of what I’ve done so far, and hopefully this will help you get started, as well.

Starting with the Basics

The first step is to gain a basic understanding of the following:

  • What is a blockchain?
  • What is Bitcoin?
  • What is Ethereum?
  • How are Bitcoin and Ethereum different?
  • What is a decentralized application, or DApp?

This isn’t hard to do; there are numerous videos detailing the above.

The specifics of the development workflow is where I got stuck.

The Big Picture - How to Develop on Ethereum

DApps running on the Ethereum network can be composed of the following parts:

  • Smart Contracts - Blockchain code that runs in the Ethereum Virtual Machine
  • Front End UI - HTML/CSS/JS + web3.js
  • Backend Code running in the traditional way (optional)

Smart Contracts

Smart Contracts are the programs that run on the Ethereum network, in the Ethereum Virtual Machine. It is with Smart Contracts that you can query and make transactions / save data on the blockchain.

You write Smart Contracts with a language like Solidity or Vyper. These are statically typed languages compiled into bytecode that can be understood by the Ethereum Virtual Machine.

I am most familiar with C-style languages, so I got started with Solidity. It is my understanding that Solidity is the most widely used in the industry, so if your goal is a job, you’ll also want to start with Solidity.

A Smart Contract is like a class in any class-oriented (object-oriented) language, so if you are familiar with JavaScript and a class-based language like C# or even PHP, you won’t find it too difficult getting used to the syntax.

Front End and web3.js

The front end code interacts with the Smart Contracts via a library called web3.js. There are other libraries (web3.py, ethers.js), but I understand web3.js is the most used, so that is what I started with.

web3.js gives you the methods needed to query and send data to the Smart Contract. The library understands HOW to talk to the Smart Contracts on the network because of Application Binary Interface files - ABIs.

These ABI files are generated when you use a tool like Truffle - truffle compile; they are JSON files.

In your front end JavaScript, you first create a web3 object using the address of your smart contract and the relevant ABI. From there you have access to different methods that allow you to easily interact with the Smart Contract just as you would any 3rd-party API.

Centralized Backend (optional)

I haven’t quite figured this part out, yet, though I understand a lot of DApps are a mix of Smart Contracts and “traditional” backend code on a centralized server. As I get more familiar with the WHY and WHEN to use a centralized backend, I will share those insights here on the blog.

Getting Started

Step 1 - Learn the Basics with CryptoZombies

I recommend getting started with the CryptoZombies tutorial. It will help you get familiar with the basics of Solidity and Smart Contracts in general.

The lessons are bite-sized enough that you can complete a number of them in a short amount of time, and the scope isn’t so huge that you will get overwhelmed.

While this makes the tutorial easier to get through, it also means you’ll have to do a lot of practice on your own to internalize what you’ve “learned” in the tutorial. The tutorials themselves don’t offer much in the way of repetition or challenges to help you practice.

Step 2 - Build Your Own DApps

I completed the entire CryptoZombies course before I moved onto building my own application. I had to keep the tutorial open in my browser, though, for reference; there’s just too much material to remember it all in one go.

With CryptoZombies you will get familiar with using 3rd-party Smart Contracts to augment your own. OpenZeppelin is a company that has made numerous Smart Contracts / Libraries available for other developers to use. OZ’s “Proxy” contracts are battle-tested and free to use, so once you’re done with CryptoZombies, you should get to work building your own application using OZ’s Proxy Contracts.

I found out about them after asking others on Twitter what they look for in blockchain dev candidates before hiring them. Familiarity with OpenZeppelin’s proxy contracts was on that list.

Local Dev Environment Setup

There are multiple ways to set up a local dev environment. I use the above for the following reasons:

  1. Truffle is easy to use, and many jobs seem to require familiarity with the Truffle Suite of tools.
  2. Ganache is a very easy to use local blockchain, so I can get to work quickly.
  3. OpenZeppelin contracts are widely used and respected.
  4. OpenZeppelin test helpers really do make testing easier.
  5. Buidler (no, that is NOT a typo) provides great stack traces for errors and a console.log() function to make debugging A LOT easier.

Quick Start

I prefer to write tests before I start with any sort of front end code. You can lose a lot of time setting up a basic front end, especially when you go beyond basic JavaScript and start using frameworks like React / Vue. If you like those frameworks, fine, but remember the goal is to get familiar with writing Smart Contracts right now, so either keep your front end as minimal as possible, or do what I do and start with tests.

  1. mkdir my_ethereum_project && cd my_ethereum_project
  2. truffle init
  3. git init && git add . && git commit -m "init" - always use git.
  4. in tuffle-config.js uncomment
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// uncomment the following in the exported module object:
module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",     // Localhost (default: none)
      // port: 8545, // many tutorials mention this port, but my ganache defaults to 7545, so I just use that.
      port: 7545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
    },
  },
  compilers: {
    solc: {
      version: "0.6.2",    // Fetch exact version from solc-bin (default: truffle's version)
      settings: {          // See the solidity docs for advice about optimization and evmVersion
        optimizer: {
          enabled: true,
          runs: 200
        },
      }
    },
  },
}
  1. npm install --save-dev @nomiclabs/buidler @nomiclabs/buidler-truffle5 @nomiclabs/buidler-web3 @openzeppelin/contracts @openzeppelin/test-helpers truffle
  2. In the root of the project create a file buidler.config.js and paste this in:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
usePlugin("@nomiclabs/buidler-truffle5")

module.exports = {
    solc: {
        version: "0.6.2",
        optimizer: {
            enabled: true,
            runs: 200
        }
    },
}

  1. Go to ./contracts/ and create a contract, eg: SomeContract.sol

and paste the following in the file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@nomiclabs/buidler/console.sol";

contract SomeContract is Ownable {

  function sayHello() public view onlyOwner returns(string memory) {
    console.log("You'll see this in the test output!")
    return "Hello, World";
  }
}

  1. Create a new directory in the root of your project test
  2. Create a new file, eg: SomeTests.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Apply configuration
require('@openzeppelin/test-helpers/configure')({})

const {
    BN,           // Big Number support
    constants,    // Common constants, like the zero address and largest integers
    expectEvent,  // Assertions for emitted events
    expectRevert, // Assertions for transactions that should fail
} = require('@openzeppelin/test-helpers')

const SomeContract = artifacts.require("SomeContract")

describe("Some Contract", () => {
    let accounts
    let contract

    beforeEach(async () => {
        accounts = await web3.eth.getAccounts()

        contract = await SomeContract.new()
    })

    describe("sayHello()", () => {
        it("should say hello", async() => {
            const greeting = await contract.sayHello()

            assert.equal(greeting, "Hello, World")
        })
    })

})

  1. In the root of your project npx buidler test and watch the magic happen.

That should give you a decent framework to start writing your own Smart Contracts and writing tests for them.

You can get very far with your application before you have to start thinking of building a UI.

I will draw out my UI on paper to help me plan out my backend code, but after that I prefer to write the backend and use tests to verify everything works as expected. In general, I can work A LOT faster this way, and I have way more fun.

Done

If this write up has helped you at all, I would like to hear about it on Twitter.