I created a Web3 app and here's what I learned.

I created a Web3 app and here's what I learned.

An introduction to blockchain, smart contracts, and decentralized apps.


7 min read

Featured on Hashnode
Featured on daily.dev

I finally caved

I'd been hearing a lot about Web3 and reluctantly did a deep dive on it over the weekend. What really caught my eye is the idea of decentralizing the control and ownership that currently only a few companies have. I'm particularly interested in this because while building Calibaba, our biggest problem is that no payment processors allow for the sale of cannabis and cannabis products, despite it being legal in California. In the Web3 world, this wouldn't happen because of the decentralized nature of Web3 applications, no single entity on the network can block anyone from submitting transactions, taking away control to dictate what is and isn't allowed away from payment processors and the entities that govern them.

I signed up for Buildspace's course on building a Web3 app with Solidity and Ethereum smart contracts and here are some questions I'm hoping to answer in this post to help you get started with Web3:

- How does the blockchain work?

- What are accounts, transactions, and smart contracts?

- What are decentralized apps?

- What the heck is Web3, really?

Note: I'm going to keep it simple in my explanation of the blockchain because there are other blogs and docs out there with a much better handle on it. I will just be explaining what is necessary to understand the rest of the content in this post.

Blockchain Basics

There are many different Blockchains and types of blockchains. The Ethereum blockchain is a public blockchain that acts as a database that stores its data among many different computers in a network, known as "nodes." This is different from a typical database which stores all of its data in centralized servers. Right off the bat, we can recognize that one of the benefits of a public blockchain can't go down because its servers are down. Even if several computers in the blockchain go down, the network as a whole would be unaffected.

Smart Contracts

Smart contracts are the bread and butter of Web3 development. A smart contract is simply a program with executable code that lives at a specific address on the blockchain once deployed. There are open source smart contract libraries that enable developers to reuse building blocks that can save you time coding. Ethereum smart contracts are written in Solidity and the language is similar to C++/Java with a little Javascript thrown in there.

Decentralized apps

Decentralized apps, or dapps, are regular ol' applications that are built on a decentralized network (like the Ethereum blockchain) that combine a smart contract and a user interface. This is in contrast to a regular app because a dapp's backend is the decentralized network instead of servers. A dapp can have front-end code written in any language and makes calls to its back end. The front end interacts with the smart contract on the network to execute specific functions to create the desired functionality.

Wave to me over the blockchain ๐Ÿ‘‹

Tools used in this project:

  • Hardhat - "Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software. Hardhat comes built-in with Hardhat Network, a local Ethereum network designed for development."

  • Ethers.js - Ethers is a js library for interacting with the Ethereum Blockchain and its ecosystem.

  • Rinkeby TestNet - A testnet that simulates the production blockchain where developers can deploy their apps without paying gas fees.

  • Rinkeby Test Faucet - Request fake ETH to deploy to the testnet.

  • MetaMask Wallet - A wallet where you can store your fake ETH on the Rinkeby testnet.

  • Alchemy - A blockhain development platform that gives us the ability to read and write to the blockchain. They provide the node that is needed as the entrypoint to access the blockchain.

Web3 App

The dapp we built in the course allows for users to connect their wallet to get access to the network, and therefore get access to our smart contract, and allows users to 'wave' hello at us. Our smart contract keeps a count of how many waves we have received, returns the total number of waves we have received, and stores the addresses of the wallets that have waved at us in an array. Our app has three main components - the smart contract, scripts to test our smart contract functionality, and our front-end client to create an interface for users to interact with our smart contract. Our app was deployed on a testnet, a clone of Ethereum's mainnet. We did this because deploying to the actual blockchain costs money, and this is a free way to make projects. We get an ETH wallet like MetaMask, and select the Rinkeby testnet. Then, we have to request some fake eth to pay our testnet. If you want to interact with this app, you'll need to connect a MetaMask wallet. When you create a MetaMask wallet, be sure to select the Rinkeby Test Network. Then, you'll need to request some fake eth here.

Some housekeeping before moving on:

  • Transaction: an action that modifies what's currently stored in the network, or the network itself. Think of a transaction as any action that writes to our "database."

The smart contract code is super simple and looks like what you would expect coming from a language like Java or C++:

pragma solidity ^0.8.0;
import "hardhat/console.sol";

contract WavePortal {
    address[] public addresses;
    uint256 totalWaves;
        console.log("Let's gooooo");

    function wave() public {
        totalWaves += 1;
        console.log("%s has waved!", msg.sender);
        console.log("sender address pushed");

    function getTotalWaves() public view returns (uint256) {
        console.log("We have %d total waves", totalWaves);
        return totalWaves;

    function getAddresses() public view returns (address[] memory) {
        for(uint256 i = 0; i< addresses.length; i++){
            console.log("Sender addresses:", addresses[i]);
        return addresses;

Then, we create a script to interact with our smart contract and run our functionality locally:

const main = async () => {
    const waveTracker = {};
    const [owner, randoPerson] = await hre.ethers.getSigners();
    const waveContractFactory = await hre.ethers.getContractFactory('WavePortal');
    const waveContract = await waveContractFactory.deploy();
    await waveContract.deployed();

    console.log("Contract deployed to:", waveContract.address);
    console.log("Contract deployed by:", owner.address);

    //get starting count
    let waveCount;
    waveCount = await waveContract.getTotalWaves();
    //Wave transaction - we are waving to ourselves here
    let waveTxn = await waveContract.wave();
    //We have to wait until the transaction is mined (wait for the state change to be reflected in the block chain)
    await waveTxn.wait();
    //Get total after wave
    //Random person is waving to us here
    waveTxn = await waveContract.connect(randoPerson).wave();
    await waveTxn.wait();
    waveCount = await waveContract.getTotalWaves();
    txnAddresses = await waveContract.getAddresses();

  const runMain = async () => {
    try {
      await main();
    } catch (error) {


You'll notice that in our script after we wave, we update our state variable 'count.' When this gets called by a real user accessing our smart contract via the blockchain and not by our script, it will be updating a state variable on the blockchain. This is a transaction and whenever a transaction is made, there is a delay in updating the blockchain with this new information because this transaction has to be mined to become valid. Mining a transaction is the process of creating a new block of transactions to be added and propagated throughout the blockchain. Ethereum miners are just computers that are running software and lend their time and computational power to process transactions.

Then, we built our front end using React. In our React app, we connect the functions that we wrote in our smart contract and call them in the client app by using the ethers library. In order for our app to talk to the blockchain, a user needs to connect their wallet. This acts as a log-in step to authenticate a user. In our React app, we prompt users to connect their MetaMask wallets in order to get access to wave at us over the blockchain. You can view the project and the source code here.

Screen Shot 2021-09-26 at 11.08.24 PM.png

Soo... what is Web3?

In simple terms, web3 refers to a version of the internet where applications run on the blockchain. That means that every change to every app that interacts with any smart contract will be posted to the chain permanently. People are excited about Web3 because this decentralized and permanent nature would enable everyone to access the network without permission and no one or no entity could dictate what is and isn't allowed.