shoutouts.eth

shoutout

Table of Contents

  1. Backend
    1. Set Up Development Environment
    2. Create Base Project
    3. Create Infura Account
    4. Create Pinata Account
    5. Copy Mnemonic from MetaMask
    6. Install Project Dependencies
    7. Create Contract and Migration
    8. Create NFT Image
    9. Create Sample Metadata File
    10. Compile Contract
    11. Migrate to Rinkeby Network
    12. Test Deployed Contract in Console
    13. Verify the Shoutout on the Blockchain
    14. Add New Token to MetaMask
  2. Frontend
    1. Prerequisites
    2. Setup Front End Codebase
    3. Implement Front End Javascript
    4. Build + Run Frontend
    5. Build for Production
    6. Open in MetaMask Enabled Browser
  3. Deploy
    1. Using Fleek + IPFS
  4. Resources & Credits
    1. Books
    2. Guides
    3. Repositories

Backend

Set Up Development Environment

  1. Install Truffle: npm install -g truffle
  2. Install Ganache: npm install -g ganache-cli
  3. Install Fleek: npm install -g @fleekhq/fleek-cli
  4. Download and install the IPFS CLI by following these instructions.
  5. Install the Blockchain Development Kit for Ethereum extension in VSCode.

Create Base Project

mkdir shoutouts.eth
cd shoutouts.eth
truffle init
npm init
cp .env.sample .env

Create Infura Account

  1. <infura.io>: Sign up and create a new project. Give it the same name as your codebase.
  2. Under the Keys heading, copy Project Secret to your clipboard.
  3. Open your .env file and paste the key to the right of INFURA_KEY=.

Create Pinata Account

  1. Visit <pinata.cloud> and create a new account.
  2. Click API Keys on left sidebar.
  3. Click New Key
  4. Turn on Admin level access.
  5. The name of the key should match the project name.
  6. Click Create Key. A modal dialog will appear. Click Copy All and store the values somewhere safe, like in a password manager.
  7. Copy JWT to the clipboard.

Copy Mnemonic from MetaMask

  1. Open Chrome and log in to MetaMask.
  2. Click Account Icon on Top Right > Choose Settings > Security & Privacy
  3. Click Reveal Secret Recovery Phrase and enter your MetaMask password.
  4. Copy the phrase to your clipboard.
  5. Open your .env file and paste the mnemonic to the right of MNEMONIC=.

Install Project Dependencies

npm install @openzeppelin/contracts dotenv @truffle/hdwallet-provider@1.2.3

Create Contract and Migration

touch contracts/ShoutoutContract.sol
touch migrations/2_deploy_contracts.js

Create NFT Image

  1. Visit https://badge.design to generate an image for your new token.

  2. Save a transparent PNG of the image in the root of your project.

  3. Open the IPFS Desktop application.

  4. Add the image to IPFS:

    $ ipfs init
    generating ED25519 keypair...done
    peer identity: 12D3KooWK9J7NfuE9wGKWpERRLWDhcpUwhfduu4osbhV2TamQeRZ
    initializing IPFS node at /Users/droxey/.ipfs
    
    
    $ ipfs daemon
    Initializing daemon...
    go-ipfs version: 0.9.0
    Repo version: 11
    System version: arm64/darwin
    Golang version: go1.16.5
    Swarm listening on /ip4/127.0.0.1/tcp/4001
    Swarm listening on /ip4/127.0.0.1/udp/4001/quic
    Swarm listening on /ip4/192.168.0.118/tcp/4001
    Swarm listening on /ip4/192.168.0.118/udp/4001/quic
    Swarm listening on /ip4/192.168.0.173/tcp/4001
    Swarm listening on /ip4/192.168.0.173/udp/4001/quic
    Swarm listening on /ip6/::1/tcp/4001
    Swarm listening on /ip6/::1/udp/4001/quic
    Swarm listening on /ip6/fdc4:67f5:8ffa:3:144b:dbb3:b143:89a0/tcp/4001
    Swarm listening on /ip6/fdc4:67f5:8ffa:3:144b:dbb3:b143:89a0/udp/4001/quic
    Swarm listening on /ip6/fdc4:67f5:8ffa:3:cf5:b55b:8447:a756/tcp/4001
    Swarm listening on /ip6/fdc4:67f5:8ffa:3:cf5:b55b:8447:a756/udp/4001/quic
    Swarm listening on /p2p-circuit
    Swarm announcing /ip4/127.0.0.1/tcp/4001
    Swarm announcing /ip4/127.0.0.1/udp/4001/quic
    Swarm announcing /ip4/192.168.0.173/tcp/4001
    Swarm announcing /ip4/192.168.0.173/udp/4001/quic
    Swarm announcing /ip4/71.204.188.97/udp/4001/quic
    Swarm announcing /ip6/::1/tcp/4001
    Swarm announcing /ip6/::1/udp/4001/quic
    API server listening on /ip4/127.0.0.1/tcp/5001
    WebUI: http://127.0.0.1:5001/webui
    Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
    Daemon is ready
  5. In a new terminal tab, run ipfs add shoutout.png to add the token's image to IPFS:

    $ ipfs add shoutout.png
    added QmRGhvqTPvx8kgMSLFdPaCysKvhtP5GV5MsKDmTx3v2QxT shoutout.png
    10.79 KiB / 10.79 KiB [=======================================================================================================================================================] 100.00%

    Copy the hash you receive when adding the image. This is the address of your image in IPFS.

  6. Pin the image in Pinata:

    $ ipfs pin remote service add pinata https://api.pinata.cloud/psa PASTE_JWT_KEY
    $ ipfs pin remote add --service=pinata --name=shoutout.png QmRGhvqTPvx8kgMSLFdPaCysKvhtP5GV5MsKDmTx3v2QxT

Create Sample Metadata File

This sample metadata can be used prior to developing a metadata API, and exists to prove that we can mint our token successfully.

  1. Add the file to IPFS:

    $ ipfs add sample-metadata.json
    added QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j sample-metadata.json
    196 B / 196 B [===============================================================================================================================================================] 100.00%
  2. Pin the file in Pinata:

    $ ipfs pin remote add --service=pinata --name=sample-metadata.json QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j
    CID:    QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j
    Name:   sample-metadata.json
    Status: pinned

Compile Contract

$ truffle compile

Compiling your contracts...
===========================

> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/ShoutoutContract.sol
> Compiling @openzeppelin/contracts/token/ERC721/ERC721.sol
> Compiling @openzeppelin/contracts/token/ERC721/IERC721.sol
> Compiling @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
> Compiling @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol
> Compiling @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
> Compiling @openzeppelin/contracts/utils/Address.sol
> Compiling @openzeppelin/contracts/utils/Context.sol
> Compiling @openzeppelin/contracts/utils/Counters.sol
> Compiling @openzeppelin/contracts/utils/Strings.sol
> Compiling @openzeppelin/contracts/utils/introspection/ERC165.sol
> Compiling @openzeppelin/contracts/utils/introspection/IERC165.sol

> Artifacts written to /Users/droxey/dev/repos/shoutouts.eth/build/contracts
> Compiled successfully using:
   - solc: 0.8.0+commit.c7dfd78e.Linux.g++

Migrate to Rinkeby Network

$ truffle migrate --network rinkeby

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



Starting migrations...
======================
> Network name:    'rinkeby'
> Network id:      4
> Block gas limit: 10000000 (0x989680)


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0x3d7e525301cb45c617ddfc1977397e9f5ee74b1f4679851ada897994bf08e9e4
   > Blocks: 1            Seconds: 12
   > contract address:    0xAf47d95c283b8d0333ADEDAF0bB22916ceFFA7FB
   > block number:        8841341
   > block timestamp:     1624856784
   > account:             0xe4233b38fEa3B8c27ea9F54d5A90ec27cEe7F42C
   > balance:             1.556150107
   > gas used:            251534 (0x3d68e)
   > gas price:           1 gwei
   > value sent:          0 ETH
   > total cost:          0.000251534 ETH

   Pausing for 2 confirmations...
   ------------------------------
   > confirmation number: 1 (block: 8841342)
   > confirmation number: 2 (block: 8841343)

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:         0.000251534 ETH


2_deploy_contracts.js
=====================

   Deploying 'ShoutoutContract'
   ----------------------------
   > transaction hash:    0xea92115a2eb4d8d6164bcbb52714e7c42fccb9de09a060457b128fcf1877ffc6
   > Blocks: 1            Seconds: 12
   > contract address:    0x001Fd4dd63455F327BE312C6bf7c77c5A63BEe9e
   > block number:        8841345
   > block timestamp:     1624856844
   > account:             0xe4233b38fEa3B8c27ea9F54d5A90ec27cEe7F42C
   > balance:             1.553639137
   > gas used:            2465052 (0x259d1c)
   > gas price:           1 gwei
   > value sent:          0 ETH
   > total cost:          0.002465052 ETH

   Pausing for 2 confirmations...
   ------------------------------
   > confirmation number: 1 (block: 8841346)
   > confirmation number: 2 (block: 8841347)

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:         0.002465052 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.002716586 ETH

Test Deployed Contract in Console

$ truffle console --network rinkeby
truffle(rinkeby)> let instance = await ShoutoutContract.deployed()
truffle(rinkeby)> let result = await instance.awardItem("0xe4233b38fEa3B8c27ea9F54d5A90ec27cEe7F42C", "https://gateway.pinata.cloud/ipfs/QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j")

Verify the Shoutout on the Blockchain

  1. Open https://rinkeby.etherscan.io
  2. Paste the deployed contract address in the search bar or visit https://rinkeby.etherscan.io/address/DEPLOYED_CONTRACT_ADDRESS (https://rinkeby.etherscan.io/address/0x001Fd4dd63455F327BE312C6bf7c77c5A63BEe9e)
  3. Should see two transactions --- one to create the contract, and one to award an item.

Add New Token to MetaMask

  1. Open MetaMask and click Add Token
  2. Paste the deployed contract address in the Token Contract Address field.
  3. Set Token Decimal to 0.
  4. Click Next
  5. Click Add Token

Frontend

Prerequisites

  1. Sign up for an account on fleek.co (one per team)
  2. Add team members by going to the Members link on the sidebar.
  3. Go to the Storage tab on the sidebar and click Create Folder. 
  4. Name the folder metadata.
  5. Generate a Storage API Key by clicking your name at the bottom of the page, then choosing Settings. Scroll to the bottom to generate a new API key. 
  6. Use these keys in your JS to upload files on Fleek!

Setup Front End Codebase

  1. Add app folder to project. Name is important!
  2. Add app/js/index.js to the project.
  3. Add app/index.html to the project.

Implement Front End Javascript

Located in app/js/index.js.

Build + Run Frontend

In the app directory, we build and run our frontend.

Smart contract changes must be manually recompiled and migrated.

Open another terminal and run the following commands to build the frontend:

cd dev
npm run dev

Build for Production

Open a fresh terminal and run the following commands to build the frontend:

cd dev
npm run build

The production build will be in the dist folder after running npm run build in the app folder.

This build can be deployed anywhere static sites can be hosted!

Open in MetaMask Enabled Browser

Visit http://localhost:8080 in your browser to test your new full stack DApp!

Deploy

Using Fleek + IPFS

  1. Visit <fleek.co> in your browser and create an account.

  2. Run fleek login to sign in from your terminal before initializing or deploying.

  3. Initialize fleek for your project:

    $ fleek site:init
    'This command will walk you through initializing a new or existing fleek site config in the current directory.'
    
    'Successfully initializing a site would create a .fleek.json file in your directory.'
    'You can then use `fleek site:deploy` to deploy changes made to your publish directory.'
    
    ? Which team you wanna use? username-team
    ...fetching list of sites for team: username-team
    ? Which site you wanna use? Create new site
    ? Select the public directory for deployment ('.' for current directory): .
    publishing files in /Users/droxey/dev/repos/shoutouts.eth to IPFS
    packaging site contents...
    uploading...
    Site cid is QmULzpjfa3CbBRktd2744jXYqWbYjkHTYd9sbvthzkTkzx
    creating new site
    Fleek site late-dust-7939 was successfully initialized.
  4. Deploy the entire project to IPFS:

    $ fleek site:deploy
    publishing files in /Users/droxey/dev/repos/shoutouts.eth to IPFS
    packaging site contents...
    uploading...
    Site cid is QmTRnEN27nJLpXFiXEZ8NTr4wE4q5ssg9F9hqztnHrjYso
    New deployment has been triggered.
    View deployment here: https://app.fleek.co/#/sites/late-dust-7939/deploys/2021-06-28T04:34:52.361Z?accountId=username-team

Resources & Credits

Books

Guides

Repositories