Anthony Campolo
ajcwebdev

ajcwebdev

a first look at avalanche

Avalanche is an open-source, proof-of-stake blockchain with smart contract functionality that uses the Snow family of consensus protocols.

Anthony Campolo's photo
Anthony Campolo
·May 12, 2022·

8 min read

a first look at avalanche

Table of contents

Introduction

Avalanche is an open-source, proof-of-stake blockchain with smart contract functionality that uses the Snow family of consensus protocols. Avalanche features 3 built-in blockchains that are validated and secured by the Primary Network:

  • Exchange Chain (X-Chain) - Acts as a decentralized platform for creating and trading digital smart assets like AVAX. These assets are a representation of a real-world resource with a set of rules that govern its behavior. The X-Chain is an instance of the Avalanche Virtual Machine (AVM).
  • Platform Chain (P-Chain) - Metadata blockchain on Avalanche that coordinates validators, keeps track of active subnets, and enables the creation of new subnets. The P-Chain implements the Snowman consensus protocol.
  • Contract Chain (C-Chain) - Allows for the creation smart contracts using the C-Chain’s API.

00-avalanche-primary-network-diagram.png

All the code for this example can be found on my GitHub.

Configure MetaMask Wallet for Avalanche

You can create an Avalanche Wallet online at wallet.avax.network or you can configure an existing wallet that allows connecting to RPC endpoints. We will use MetaMask in this tutorial which you can download here.

Add Avalanche Network

Open MetaMask and check the available networks. If you just installed the extension, you will only see Ethereum Mainnet.

01-add-network-to-metamask-wallet.png

Click "Add Network" to configure MetaMask for the Avalanche network and include the following information for the Fuji Testnet:

  • Network Name: Avalanche FUJI C-Chain
  • New RPC URL: https://api.avax-test.network/ext/bc/C/rpc
  • ChainID: 43113
  • Symbol: AVAX
  • Explorer: https://testnet.snowtrace.io/

02-fuji-network.png

Also include the information for Mainnet:

  • Network Name: Avalanche Network
  • New RPC URL: https://api.avax.network/ext/bc/C/rpc
  • ChainID: 43114
  • Symbol: AVAX
  • Explorer: https://snowtrace.io/

You will now see the Avalanche logo and "Avalanche FUJI C-Chain" written at the top.

03-metamask-configured-for-avalanche.png

Fuji Testnet Faucet

To interact with Fuji, we need to have AVAX in your wallet. Like the Ropsten faucet on Ethereum, Avalanche has the Fuji Testnet Faucet. Include your wallet address and click "Request 10 AVAX."

04-fuji-testnet-faucet.png

Return to your wallet and you should now have 10 AVAX.

05-avalanche-wallet-with-avax-funds.png

Create Project

We will use the Vite React template and install dependencies for Hardhat, Ethers, and dotenv to manage environment variables.

yarn create vite ajcwebdev-avalanche --template react
cd ajcwebdev-avalanche
yarn add -D dotenv hardhat ethers @nomiclabs/hardhat-ethers

Create the directories and files for your smart contract, Hardhat deployment script, and Hardhat configuration.

mkdir contracts scripts
touch contracts/HelloWorld.sol scripts/deploy.js hardhat.config.js

Create a .env file to hold environment variables for our endpoint URL, private key, and contract address.

echo 'QUICKNODE_URL=\nPRIVATE_KEY=\nVITE_CONTRACT_ADDRESS=' > .env

Add .env to .gitignore so you don't commit any private information.

echo '.env' >> .gitignore

Hello World Solidity Contract

Our HelloWorld contract will have a string variable called helloMessage. The hello function will return the value set to helloMessage. The setHello function will change the value of helloMessage to whatever argument is passed into the function.

// contracts/HelloWorld.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.6;

import "hardhat/console.sol";

contract HelloWorld {
  string private helloMessage;

  constructor(string memory _helloMessage) {
    console.log(_helloMessage);
    helloMessage = _helloMessage;
  }

  function hello() public view returns (string memory) {
    return helloMessage;
  }

  function setHello(string memory _helloMessage) public {
    console.log("Changing helloMessage from '%s' to '%s'", helloMessage, _helloMessage);
    helloMessage = _helloMessage;
  }
}

Now that we have created our smart contract, let's look at the script we will use to deploy this contract to Avalanche.

Deployment Script

Our deployment script in deploy.js calls the getContractFactory method on the ethers library and passes in HelloWorld as the name of the contract. HelloWorldFactory is deployed with the message Hello from ajcwebdev and set to helloMessage which is called on the next line with the deployed method. The address and signer for the contract are logged to the console.

// scripts/deploy.js

async function main() {
  const HelloWorldFactory = await ethers.getContractFactory("HelloWorld")
  const helloMessage = await HelloWorldFactory.deploy("Hello from ajcwebdev")
  await helloMessage.deployed()

  console.log("Contract deployed to:", helloMessage.address)
  console.log("Contract deployed by " + JSON.stringify(helloMessage.signer) + " signer")
  process.exit(0)
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error)
    process.exit(1)
  })

Now that we have our contract and a script to deploy it, the last step is to write our Hardhat configuration.

Hardhat Configuration

The Hardhat configuration includes the Solidity version, path for the contract artifacts, and network information.

// hardhat.config.js

require("dotenv").config()
require("@nomiclabs/hardhat-ethers")

module.exports = {
  solidity: "0.8.6",
  paths: {
    artifacts: './src/artifacts',
  },
  networks: {
    fuji: {
      url: process.env.QUICKNODE_URL,
      accounts: [`0x` + process.env.PRIVATE_KEY],
      chainId: 43113,
    },
  },
}

We need to include two environment variables in .env before we can deploy this contract. Set your Avalanche wallet's private key to the PRIVATE_KEY variable. Now we will visit QuickNode to deploy our RPC endpoint.

Deploy Avalanche Node on QuickNode

First you will need to create an account on QuickNode by filling in the form on the homepage.

Create an Endpoint

After creating an account, you will see the following screen.

06-create-an-endpoint-on-quicknode.png

Click the "Create an endpoint" button to see the available blockchains.

07-choose-a-chain-and-network.png

After selecting Avalanche you will be asked whether you want a node on Mainnet or the Fuji Testnet. Select Fuji.

08-select-your-avalanche-network.png

You'll be asked if you want any of the add-ons including Archive Mode or Trace Mode. You'll then be asked for your credit card information but you will not be charged for the first seven days.

09-avalanche-endpoint-on-quicknode.png

Copy the HTTP provider URL and paste it into your .env file. Include /ext/bc/C/rpc at the very end of the URL to specify that you want to connect to the C-Chain, an instance of the Ethereum Virtual Machine that allows for creating smart contracts with the C-Chain’s API.

Deploy Contract to Fuji

Before deploying the contract we need to first compile the contract.

yarn hardhat compile

Deploy the contract and include a --network flag to specify the Fuji test network.

yarn hardhat run scripts/deploy.js --network fuji

You will receive an output that looks like the following but with your own addresses:

Contract deployed to: 0x873E3BB2A752DBDFA06017CC5a709600Ac3c0153
Contract deployed by "<SignerWithAddress 0x6b492Ef06CA3b462f20db50EB288fAbB1E3e8Bfc>" signer

Go to Snowtrace Testnet and search for your contract address.

10-contract-on-snowtrace.png

Include the contract address in .env so it can be accessed from our frontend client in the next section.

Create React App

Our contract address can now be used to create a frontend client with React that interacts with the contract's methods.

// src/App.jsx

import { useState } from 'react'
import { ethers } from 'ethers'
import HelloWorld from './artifacts/contracts/HelloWorld.sol/HelloWorld.json'

const contractAddress = import.meta.env.VITE_CONTRACT_ADDRESS

function App() {
  const [hello, setHelloValue] = useState()

  async function requestAccount() {
    await window.ethereum.request({ method: 'eth_requestAccounts' })
  }

  async function fetchHello() {
    if (typeof window.ethereum !== 'undefined') {
      await requestAccount()
      const provider = new ethers.providers.Web3Provider(window.ethereum)
      const contract = new ethers.Contract(contractAddress, HelloWorld.abi, provider)
      try {
        const data = await contract.hello()
        setHelloValue(data)
        console.log('Greeting: ', data)
        console.log('Contract Address: ', contract.address)
      } catch (err) {
        console.log("Error: ", err)
      }
    }
  }

  return (
    <div>
      <header>
        <h1>Avalanche</h1>
      </header>

      <main>
        <h3>Hello World</h3>

        <button onClick={fetchHello}>
          Click me, you know you want to
        </button>

        <div>{hello}</div>
      </main>
    </div>
  )
}

export default App

Include the following in the head of index.html.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">

This provides default styles with Water.css.

Start Development Server

Run the following command to start the development server with Vite.

yarn dev

Open localhost:3000 to see the application.

11-avalanche-react-app.png

Click the button. You know you want to.

12-click-button-for-hello-message.png

The message will be displayed on the screen and logged to the console. Return to App.jsx and add the following after fetchHello but before the return statement begins:

// src/App.jsx

async function setHello() {
  if (!hello) return
  if (typeof window.ethereum !== 'undefined') {
    await requestAccount()
    const provider = new ethers.providers.Web3Provider(window.ethereum)
    const signer = provider.getSigner()
    const contract = new ethers.Contract(contractAddress, HelloWorld.abi, signer)
    const transaction = await contract.setHello(hello)
    await transaction.wait()
    fetchHello()
  }
}

Include the following in the return statement below fetchHello button:

// src/App.jsx

<input
  onChange={e => setHelloValue(e.target.value)}
  placeholder="Set hello message"
/>
<button onClick={setHello}>
  Set hello message
</button>

Now when you enter a new hello message and click the "Set hello message" button, you will be asked to confirm the transaction from your MetaMask wallet.

13-confirm-transaction-with-metamask.png

After confirming the transaction, it will be pending for a few seconds. Once the transaction settles you will see the new message logged to the console.

14-new-greeting-displayed-in-the-console.png

Configure Netlify Deployment

Our hello world application is complete and we can deploy it to the internet with a service like Netlify or Vercel. Create a netlify.toml file for our Netlify configuration.

touch netlify.toml

Add the following instructions:

[build]
  publish = "dist"
  command = "yarn build"

The build command is set to yarn build and the publish directory is set to dist.

Create GitHub Repository

Initialize a Git repository and push the project to a GitHub repo.

git init
git add .
git commit -m "let it snow let it snow let it snow"
gh repo create ajcwebdev-avalanche --public --push \
  --source=. \
  --description="Deploy a smart contract to Avalanche's Fuji Testnet with Hardhat, Ethers, and QuickNode" \
  --remote=upstream

I used the GitHub CLI but you can also visit repo.new and follow the instructions provided.

Deploy to Netlify

Go to your Netlify dashboard, click "Add new site," and select the newly created repo.

15-import-project-from-git-repository-on-netlify.png

Your build settings will be imported from the netlify.toml file. The only other information you need to include is your contract address under "Advanced build settings." Lastly, click "Deploy site."

16-include-environment-variable-for-contract-address-on-netlify.png

Go to "Domain settings" to give your site a custom domain. You can see this example at ajcwebdev-avalanche.netlify.app.

17-deployed-website-on-netlify.png

Resources

Did you find this article valuable?

Support Anthony Campolo by becoming a sponsor. Any amount is appreciated!

See recent sponsors Learn more about Hashnode Sponsors
 
Share this