How to Create a dApp on Avalanche's Fuji Testnet with QuickNode

June 16, 2022

Overview

Avalanche is an open-source, proof-of-stake blockchain with smart contract functionality that uses the Snow family of consensus protocols. The Avalanche Primary Network consists of 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 represent 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) - Coordinates validators, keeps track of active subnets, and enables the creation of new subnets as the metadata blockchain on Avalanche. The P-Chain implements the Snowman consensus protocol.
  • Contract Chain (C-Chain) - Allows for the creation of smart contracts using the C-Chain’s API.

Avalanche is one of several new Layer 1 blockchains that are competing to draw Ethereum developers. For a simpler onboarding experience for Ethereum developers, Avalanche's smart contracts can be written in Solidity. Avalanche's consensus mechanism aims to enable developing applications that are faster, cheaper, and more energy efficient than competing chains.

avalanche-primary-network-diagram

In this guide, we’ll walk through setting up a wallet for the Avalanche network, deploying a smart contract, and connecting a frontend application to that contract. By the end, you’ll have a dApp connected to the Avalanche Fuji testnet.

What You Will Do

  • Configure your Coinbase Wallet for the Avalanche network
  • Deploy a smart contract written in Solidity to the Fuji Testnet
  • Create a React frontend application that reads and writes to the contract

What You Will Need

Set Up Avalanche API on QuickNode

To build on Avalanche, you'll need an API endpoint to talk to on their network. If you'd like to deploy, host, and manage your own infrastructure, you can skip this section. If you'd like to leave the heavy lifting to us, you can sign up for a free, 7-day trial. First, create an account on QuickNode by filling in the form on the homepage.

Create an Endpoint

Once you’ve created an account, you should see the following screen.
create-an-endpoint-on-quicknode

Click the "Create an endpoint" button and select the "Avalanche" chain.
choose-a-chain-and-network

We’ll be working with the Fuji Testnet for this guide, so go ahead and select the "Fuji Testnet" for the network.
select-your-avalanche-network

You will then have the option to set up any additional functionality, including Archive Mode or Trace Mode. You can skip those for this guide and complete the setup by submitting your payment information. Your card will not be charged for the first seven days.
avalanche-endpoint-on-quicknode

Configure Coinbase Wallet for Avalanche

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

Add Avalanche Network

Open your Coinbase Wallet and enable Developer Mode in the Settings tab. In the same tab, check the available networks by selecting "Default network" and selecting "Avalanche Fuji" under testnets.


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 2 AVAX."
fuji-testnet-faucet

Return to your wallet. You should now have 2 AVAX.

Create a New Project

Vite is a modern, frontend build tool and open source project that offers an alternative to Webpack. You can use it to create a new project with the Vite React template that is very similar to the type of project created by create-react-app. We’ll use it to connect to the smart contract deployed later in the tutorial.

Open a Terminal window and run the following commands to set it up:

create a new project

Copy
yarn create vite getting-started-with-avalanche --template react
cd getting-started-with-avalanche

After generating the boilerplate app, install dependencies for hardhat, ethers, @nomiclabs/hardhat-ethers, and dotenv to manage environment variables:

create a new project

Copy
yarn add -D dotenv hardhat ethers @nomiclabs/hardhat-ethers

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

create a new project

Copy
mkdir contracts scripts
echo > contracts/HelloWorld.sol
echo > scripts/deploy.js
echo > hardhat.config.js

Create a .env file in the root directory of your project to hold environment variables for our endpoint URL, private key, and contract address.

create a new project

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

Add .env to .gitignore so you do not commit any private information.

create a new project

Copy
echo '.env' >> .gitignore

Create a Hello World Solidity Contract


Next, we’ll add a boilerplate smart contract, HelloWorld, to deploy to Avalanche. Open a code editor of choice and paste this code into contracts/HelloWorld.sol:

create a new project

Copy
// 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;
  }
}


The contract has a string variable called helloMessage. It contains a hello function which returns the value set to helloMessage. Another function, setHello, changes the value of helloMessage to whatever argument is passed into the function.

Now that we have created our smart contract, let’s deploy it to Avalanche!


Write the Deployment Script


Add the following deployment script to scripts/deploy.js:

create a new project

Copy
// scripts/deploy.js

async function main() {
  const HelloWorldFactory = await ethers.getContractFactory("HelloWorld")
  const helloMessage = await HelloWorldFactory.deploy("Hello from QuickNode")
  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)
  })

The main function 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 QuickNode" and set to helloMessage. This is then called on the next line with the deployed method. Lastly, the address and signer for the contract are logged to the console.

Hardhat Configuration


Now that we have our contract and a script to deploy it, the last step is to write our Hardhat configuration. The configuration specifies where the contract artifacts are placed in the project and what network the contract is deployed to.

The code for it looks like this:

create a new project

Copy
// 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,
    },
  },
}

Here we specify the Solidity version, the path for the contract artifacts, and the network information for Fuji. Add this code to the hardhat.config.js file.

Before we can deploy this contract, we need to include two environment variables in .env . Navigate to the Coinbase Wallet extension and click on "Show Recovery Phrase". Copy your private key and set it to the PRIVATE_KEY variable.

Next, visit the QuickNode dashboard and copy the HTTP provider URL for your endpoint. Paste the URL into your .env file and include /ext/bc/C/rpc at the very end of the URL to specify that you want to connect to the C-Chain. This chain is 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. Run the following command:

create a new project

Copy
yarn hardhat compile

Then, deploy the contract and include a --network flag to specify the Fuji test network.

create a new project

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

If everything in your project is set up correctly, after running this script your terminal outputs the following message 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.

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

Create a React App

Our contract address can now be used to create a frontend client with React that interacts with the contract's methods. Add the following React code to src/App.jsx to set up your app:  

create a react app

Copy
// 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

Next, navigate to the index.html and include the following stylesheet in the head of the html:

create a react app

Copy
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/out/water.css">

This provides default styles with Water.css.

Start Development Server

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

create a react app

Copy
yarn dev

Enter localhost:3000 to see the application:

avalanche-react-app

Let's test it! Connect your wallet and click the button below "Hello World".  

click-button-for-hello-message

You should see a greeting message displayed below the button and logged to the console. 

Now, let's update our code with one more feature. Return to src/App.jsx and add the following setHello function after fetchHello but before the return statement:

create a react app

Copy
// 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 code in the return statement below the fetchHello button:

create a react app

Copy
// 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 are asked to confirm the transaction from your Coinbase Wallet. After confirming the transaction, it is pending for a few seconds. Once the transaction settles, the new message is logged to the console.
new-greeting-displayed-in-the-console


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.

create a react app

Copy
echo > netlify.toml

Add the following instructions to the netlify.toml file:

create a react app

Copy
# netlify.toml

[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.

create a react app

Copy
git init
git add .
git commit -m "add initial commit message here"
gh repo create getting-started-with-avalanche --public --pu \
  --source=. \
  --description="Deploy a smart contract to Avalanche's Fuji Testnet with Hardhat, Ethers, and QuickNode" \
  --remote=upstream

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

Deploy to Netlify

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

import-project-from-git-repository-on-netlify

Your build settings are 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."

include-environment-variable-for-contract-address-on-netlify

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

Congratulations! You should see your site live at your custom domain similar to this:  

deployed-website-on-netlify

Conclusion

That is a wrap! In this guide, you have learned how to configure Coinbase Wallet for the Avalanche network, deploy a smart contract written in Solidity to Avalanche's Fuji Testnet, and create a React frontend application for reading and writing to the contract.

Subscribe to our newsletter for more articles and guides. Feel free to reach out to us via Twitter if you have any feedback. You can always chat with us on our Discord community server, featuring some of the coolest developers you'll ever meet :)

Related articles 54

How to Send a Transaction On Solana Using JavaScript
Apr 13, 2022

Hello reader! Today is an exhilarating day because we are going on an expedition to the Solana Blockchain. Solana is an up-and-coming blockchain seeking to improve upon the current ecosystem's solutions to the complex problem of providing a secure, scalable, decentralized...

Continue reading
How to do a non-custodial transaction with QuickNode
Apr 12, 2022

Private keys are one of the most sensitive pieces of data when it comes to cryptography and the blockchain. However, there has always been debate/confusion about choosing between custodial wallets (where the wallet provider has custody of the user’s private key) and...

Continue reading
How to connect to Ethereum using .NET (Nethereum)
Apr 12, 2022

Dotnet or .NET is very popular for the development of desktop applications, most Windows desktop applications are built using .NET, and it also contributes largely to web application’s tech stack. In this guide, let’s see how we can connect to Ethereum using .NET and

Continue reading
How to Set Up a Near Project from Scratch
Jan 27, 2022

In this tutorial we will look at how we can setup a basic NEAR project from scratch, installing and configuring dependencies and customizing the project to work well with AssemblyScript.We will first start by initializing our project with a package.json file using...

Continue reading
Como crear y lanzar un ERC-721 (NFT)
Dec 29, 2021

Coleccionables digitales que son compatibles con ERC-721 se han vuelto muy populares desde el lanzamiento de Cryptokitties y han ganado adopción masiva en los últimos meses. Esta guía cubrirá la parte de creación y lanzamiento...

Continue reading
How to connect to Ethereum network using Java / Web3j
Apr 12, 2022

We can say that Java is one of the most versatile languages out there, and it continues to be relevant in today's time. Java is so popular because of its massive user base and use cases. In this guide/tutorial, we'll learn how to connect to the Ethereum Blockchain network...

Continue reading
How to integrate IPFS with Ethereum
Apr 12, 2022

It can be costly to store massive files on a blockchain mainnet, and this is where decentralized file storing systems like IPFS can come in handy. Sometimes, NFTs use IPFS as well. In this guide, we’ll cover how we can integrate IPFS with...

Continue reading
How to Connect to the Ethereum Network using Ruby
Jun 13, 2022

The Ruby programming language has a huge fanbase. Ruby was developed by its creator with an intention to invent a language developers can enjoy learning and using. Ruby has been largely accepted by developers all around the world since its launch, in fact, the biggest...

Continue reading
How to connect to Ethereum network with ethers.js
Apr 12, 2022

When someone thinks of developing a dApp the first tool that comes to their mind is web3.js which is pretty common because of its popularity in the community and wide use cases, dApp development has been consistently growing and there are a lot of developers who want to...

Continue reading
How to Mint an NFT on Solana
Apr 12, 2022

Updated at: April 10, 2022Welcome to another QuickNode guide on Solana - the up-and-coming blockchain that seeks to solve the scalability issues of Ethereum. We will be walking through step-by-step how to create an NFT on Solana. NFT, short for Non Fungible Token,...

Continue reading
The Web3 Developer Stack
Apr 12, 2022

A developer stack is a bag of technologies a developer possesses. For example, MEAN (MongoDB, Express.js, AngularJS/Angular, and Node.js) and MERN (MongoDB, Express.js, React, and Node.js) are common web developer stacks. Similarly, today we will learn more about the web3...

Continue reading
How to deploy a smart contract with Brownie
Apr 12, 2022

Python is one of the most versatile programming languages; from researchers running their test models to developers using it in heavy production environments, it has use cases in every possible technical field. In today's guide, we will learn about Brownie, a Python-based...

Continue reading
How to Get All Tokens Held by a Wallet in Solana
Jun 24, 2022

Hello readers! To kick off Solana Summer and the current whitelist meta, we thought it would be helpful to dig into all of the token accounts you and your users have using the getParsedProgramAccounts method. This tool is convenient for querying different...

Continue reading
Introduction to Scaffold-ETH 🏗
Dec 29, 2021

Developing applications involves juggling several moving pieces like front-ends, back-ends, and databases. But developing a decentralized application on a blockchain adds a few more elements like smart contracts and nodes that allow you to connect to the...

Continue reading
Como crear un NFT en SOLANA
Dec 29, 2021

¡Hola querido lector! Bienvenidos a una nueva guía de Solana.Solana es una blockchain que promete mucho a la hora de intentar resolver los problemas de escalabilidad que podemos apreciar en otras blockchains, como Ethereum por...

Continue reading
How to Get Transaction Logs on Solana
Jun 28, 2022

Ever need to pull all the transactions associated with a Wallet? Want to see all of the mint transactions associated with a Candy Machine? Or maybe see transaction history of an NFT? Solana's getSignaturesForAddress method is a versatile tool that makes...

Continue reading
How to Send an EIP-1559 Transaction
Apr 12, 2022

While Ethereum has been trying to scale, it has encountered some gas price issues. Many layer 2 solutions and sidechains sprang into existence to solve this problem, but Ethereum is the main chain, and at some point, it has to be improved. EIP-1559 was introduced to...

Continue reading
How to Create an Address in Solana using JavaScript
Apr 12, 2022

Hello reader! Welcome to QuickNode's first Solana guide. Solana is an up-and-coming blockchain that seeks to solve the scalability issues that Ethereum has been handling. You will walk through step-by-step how to create a Solana address using the @solana/web3.js...

Continue reading
How to create your own DAO with Aragon
Apr 12, 2022

Blockchain provides us with the power of decentralization. Decentralization means the transfer of power to users/members rather than having a single centralized authority governing everything; it enables various use cases in finance, governance, voting, fundraising, etc....

Continue reading
How to Connect to Terra with JavaScript using Terra.js
Apr 12, 2022

Stablecoins have been bridging the gap between traditional currencies and blockchains. Stablecoins offer stable price tokens pegged by a reserve asset which is often a fiat current like USD, EUR, GBP. The Terra protocol provides a framework to work with stablecoins. This...

Continue reading
How to connect to Ethereum network using Go
Apr 12, 2022

Go helps you make faster scalable backends and this guide will show you how to connect your backend to Ethereum (and make it even faster, more reliable, and globally accessible, all thanks to QuickNode’s global infrastructure). What is...

Continue reading
How To Fork Ethereum Mainnet with Hardhat
Apr 12, 2022

Forking the chain at an older block of the blockchain is helpful if you want to simulate the blockchain’s state at that block; Hardhat has this functionality built in. In this guide, let’s go through the process of forking the Ethereum Mainnet at an older...

Continue reading
How to connect to Ethereum using PHP
Apr 12, 2022

PHP is a very popular choice among developers and has a vast community due to its long presence in web development. In this guide, we’ll cover how to connect to Ethereum with PHP using the web3.php...

Continue reading
How to use Subspace with QuickNode
Apr 12, 2022

In this guide, we'll understand a bit about reactive development and how to use Subspace with QuickNode.JavaScript is the programming language behind most of the internet apps and websites. JavaScript today has become one of the most used programming languages,...

Continue reading
How to Connect Your Dapp With MetaMask Using Ethers.js
Dec 29, 2021

In our dApp, we will have a simple react user interface that has a material button asking the user to connect to MetaMask. And if they do not have an account, they can create one or log in to their account. They will then view their wallet balance and address displayed on...

Continue reading
How to generate a new Ethereum address in Go
Dec 29, 2021

Golang is very popular among backend developers for building infrastructures and microservices. Go is a procedural programming language. Developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google, then launched in 2009 as...

Continue reading
How to generate a new Ethereum address in Python
Dec 29, 2021

Python is one of the most versatile programming languages out there with an abundance of use cases; We can build many applications with Python from client-side to back end. In this guide, we will cover creating an Ethereum address in Python using the

Continue reading
How to Lazy Mint an NFT on Rarible with Rarepress
Apr 12, 2022

NFTs are great for creators to monetize their artwork and for people to get ownership of an item. But since gas prices are usually high given the highly in-demand space on Ethereum, minting an NFT or an NFT collection can become costly for a creator. Lazy minting solves...

Continue reading