Building a full-stack dApp using React, Ethers.js, Solidity, and Hardhat In this tutorial, you will learn a web3 technology stack that will allow you to leverage the Ethereum Virtual Machine (EVM) to build full-stack applications on dozens of blockchain networks including Ethereum, Polygon, Avalanche, Celo, and many others. The code for this project is here. The video course for this tutorial is here. Also check out Defining the web3 stack I recently joined Edge & Node as a Developer Relations Engineer and have been diving deep into smart contract development on Ethereum. I have identified what I believe is the best stack for building a full-stack dApp using Solidity: ▶︎ Client-side framework - React ▶︎ Ethereum development environment — Hardhat ▶︎ Ethereum network client library - Ethers.js ▶︎ API layer - The Graph Protocol The problem I had when learning this though was that while there was pretty good documentation for each of these things, there wasn't really anything on how to put all of these things together and understand how they all worked with each other. There are some really good templates out there like scaffold-eth (which also includes Ethers, Hardhat, and The Graph) but it can be too much for someone just getting started. I wanted an end-to-end guide that showed me how to build a full-stack Ethereum application using the latest resources, libraries, and tools. Things I'm interested in are:
After spending some time figuring all of this out and starting to use a stack that I’m pretty happy with, I thought it would be nice to write down how to build and test a full stack Ethereum application using this stack, not only for other people out there who might be interested in this stack, but also for my own future reference. This article is that reference. Each partLet’s review the main parts we’ll be using and how they fit into the stack. 1. Ethereum development environment When building smart contracts, you will need a way to deploy contracts, run tests, and debug Solidity code without having to deal with a live environment. You also need a way to compile your Solidity code into code that can be run in a client application - in our case, a React application. We'll look at how this works in detail later. Hardhat is an Ethereum development environment and framework designed for full-stack development, and is the framework I will use for this tutorial. Other similar tools in the ecosystem are Ganache, Truffle, and Foundry. 2. Ethereum network client library In our React application, we need a way to interact with our deployed smart contract. We will need a way to read data as well as send new transactions. ethers.js aims to be a complete and compact library for interacting with the Ethereum blockchain and its ecosystem from client-side JavaScript applications like React, Vue, Angular, or Svelte. This is the library we will use. Another popular option in the ecosystem is web3.js 3. Metamask Metamask helps handle account management and connects the current user to the blockchain. MetaMask enables users to manage their accounts and keys in several different ways while isolating them from the site context. Once a user has connected their MetaMask wallet, you as a developer can interact with the globally available Ethereum API (window.ethereum) which recognizes users of web3 compatible browsers as MetaMask users, and whenever you request a signature for a transaction, MetaMask will prompt the user in the most understandable way possible. 4. React React is a front-end JavaScript library for building web applications, user interfaces, and UI components. It is maintained by Facebook and many individual developers and companies. React and its vast ecosystem of meta-frameworks (like Next.js, Gatsby, Redwood, Blitz.js, etc.) support all types of deployment targets, including traditional SPAs, static site generators, server-side rendering, and combinations of all three. React seems to continue to dominate the front-end space, and I think it will continue to do so for at least the near future. 5. The Graph For most applications built on blockchains like Ethereum, reading data directly from the chain is difficult and time-consuming, so you used to see people and companies build their own centralized index servers and serve API requests from those servers. This requires a lot of engineering and hardware resources and undermines the security properties required for decentralization. The Graph is an indexing protocol for querying blockchain data that makes it possible to create fully decentralized applications and solves this problem, providing a rich GraphQL query layer that applications can use. In this guide, we will not build a subgraph for our application, but will do so in a later tutorial. To learn how to build a blockchain API with The Graph, check out Building a GraphQL API on Ethereum. What we will buildIn this tutorial, we will build, deploy, and connect several basic smart contracts:
We will also build a React frontend that allows users to:
Prerequisites
For this guide, you do not need to own any Ethereum as we will be using fake/test Ether on a test network throughout the tutorial. startFirst, we'll create a new React application: Next, move into the new directory and install ethers.js and hardhat using NPM or Yarn: Install and configure the Ethereum development environment Next, initialize a new Ethereum development environment using Hardhat: You should now see the following section created for you in your root directory:
Due to a MetaMask configuration issue, we need to update the chain ID on the HardHat configuration to 1337. We also need to update the artifact location of the compiled contract to be in the src directory of the React application. To make these updates, open hardhat.config.js and update module.exports to look like this: Our Smart ContractNext, let's look at the example contract provided to us in contracts/Greeter.sol: This is a very basic smart contract. When deployed, it sets a Greeting variable and exposes a function (greet) that can be called to return a greeting. It also exposes a function (setGreeting) that allows the user to update the greeting. When deployed to the Ethereum blockchain, these methods will be available for user interaction. Read and write to the Ethereum blockchainThere are two ways to interact with a smart contract, reading or writing/transactional. In our contract, greet can be thought of as reading, while setGreeting can be thought of as writing/transactional. When writing or initializing a transaction, you must pay for the transaction to be written to the blockchain. To do this, you need to pay Gas, which is the fee or price required to successfully conduct transactions and execute contracts on the Ethereum blockchain. As long as you are only reading data from the blockchain and not changing or updating anything, you do not need to perform a transaction and there is no gas or cost for doing so. The functions you call are then only executed by the nodes you are connected to, so you do not pay anything and reads are free. In our React application, the way we interact with the smart contract is by using a combination of the ethers.js library, the contract address, and the ABI that will be created from the contract by hardhat. What is ABI? ABI stands for Application Binary Interface. You can think of it as an interface between your client application and the Ethereum blockchain where the smart contracts you will interact with are deployed. ABIs are often compiled from Solidity smart contracts by development frameworks such as HardHat. You can also often find the ABI of a smart contract on Etherscan. Compiling ABINow that we have understood the basics of smart contracts and know what an ABI is, let’s compile an ABI for our project. To do this, go to the command line and run the following command: You should now see a new folder called artifacts in your src directory. The artifacts/contracts/Greeter.json file contains the ABI as one of its properties. When we need to use the ABI, we can import it from our JavaScript file: We can then reference the ABI like this: Note that Ethers.js also enables human-readable ABI, but we won’t cover that in this tutorial. Deploy and use a local network/blockchainNext, let’s deploy our smart contract to the local blockchain so we can test it. To deploy to your local network, you first need to start a local test node. To do this, open the CLI and run the following command: When we run this command you should see a list of addresses and private keys. These are 20 test accounts and addresses created for us that we can use to deploy and test our smart contracts. Each account also has 10,000 test ether loaded into it. Later, we will learn how to import the test account into MetaMask so that we can use it. Next, we need to deploy the contract to the test network. First, update the name of scripts/sample-script.js to scripts/deploy.js. Now we can run the deployment script and provide a flag to the CLI that we want to deploy to our local network: After executing this script, the smart contract should be deployed to the local test network, and we should then be able to start interacting with it. When the contract was deployed, it used the first account we created when we started the local network. If you look at the output of the CLI, you should be able to see something like this: This address is what we will use in our client application to talk to the smart contract. Keep this address available as we will need to use it when connecting to it from our client application. To send transactions to the smart contract, we need to connect our MetaMask wallet using one of the accounts we created when running the npx hardhat node. In the list of contracts logged out of the CLI, you should see the Account number and Private Key : We can import this account into MetaMask in order to start using some of the Eth test coins available there. To do this, first open MetaMask and enable the test network: Next, update the network to Localhost 8545: Next, in MetaMask, click “Import Accounts” from the accounts menu: Copy and paste one of the Private Keys logged out via the CLI and click Import. Once the account is imported you should see Eth in your account: Now that we have a smart contract deployed and an account to use, we can start interacting with it from our React application. Connecting the React ClientIn this tutorial we're not going to worry about building a nice UI with CSS and all that, we're going to focus 100% on the core functionality to get you up and running. You can take it from there and make it look nice if you want. That being said, let's review the two goals we want to achieve from a React application:
Knowing this, how do we do this? To achieve this, we need to do the following:
To do this, open src/App.js and update it with the following code, setting the value of greeterAddress to the address of your smart contract. To test it, start the React server: When the application loads, you should be able to get the current greeting and log it out to the console. You should also be able to update the greeting by signing the contract with your MetaMask wallet and using Ether test coins. Deploy and use a live test networkThere are several Ethereum test networks like Ropsten, Rinkeby or Kovan that we can also deploy to in order to get a publicly accessible version of the contract without having to deploy it to the mainnet. In this tutorial, we will deploy to the Ropsten test network. First, start by updating your MetaMask wallet to connect to the Ropsten network. Next, send yourself some test Ether to use throughout the rest of this tutorial by visiting this test faucet. We can access Ropsten (or any other test network) by signing up with a service like Infura or Alchemy (I use Infura in this tutorial). Once you create an application in Infura or Alchemy, you will get an endpoint that looks like this: Be sure to set ALLOWLIST ETHEREUM ADDRESSES in your Infura or Alchemy application configuration to include the wallet address of the account you will be using for deployment. To deploy to the test network, we need to update our hardhat configuration with some additional network information. One of the things we need to set up is the private key of the wallet we will be deploying from. To get your private key, you can export it from MetaMask. I would recommend not hard coding this value in your application, but instead setting it as something like an environment variable. Next, add a network property with the following configuration: To deploy, run the following script: Once the contract is deployed, you should be able to start interacting with it. You should now be able to view the live contract on the Etherscan Ropsten testnet explorer Minting TokensOne of the most common use cases for smart contracts is creating tokens, let’s look at how we can do that. We’ll go a little faster now that we understand a little more about how all of this works. Create a new file called Token.sol in the main contracts directory. Next, update Token.sol with the following smart contract: Please note that this token contract is for demonstration purposes only and is not ERC20 compliant. We will cover ERC20 tokens here This contract will create a new token called “Nader Dabit Token” and set the supply to 1,000,000. Next, compile the contract: Now, update the deploy script in scripts/deploy.js to include this new token contract: We can now deploy this new contract locally or to the Ropsten network: Once the contract is deployed, you can start sending these tokens to other addresses. To do this, let's update the client code we need to make it work: Next, run the application: We should be able to click "Get Balance" and see 1,000,000 coins in our account logged out to the console. You should also be able to view them in MetaMask by clicking Import Tokens: Next click on Custom Token and enter the token contract address, then add your custom token. (If asked for token decimals, select 0) Now the token should be available in your wallet: Next, let's try sending these coins to another address. To do this, copy the address of another account and then send them to that address using the updated React UI. When you check the token amount, it should be equal to the original amount minus the amount you sent to the address. ERC20 TokensThe ERC20 token standard defines a set of rules that apply to all ERC20 tokens, allowing them to easily interact with each other. ERC20 makes it easy for people to mint their own tokens that will be interoperable with others on the Ethereum blockchain. Let’s see how we can build our own token using the ERC20 standard. First, install the OpenZepplin smart contract library, into which we will import the base ERC20 token: Next, we will create our token by extending (or inheriting from) the ERC20 contract: The constructor allows you to set the token name and symbol, and the _mint function allows you to mint tokens and set the amount. By default, ERC20 sets the number of decimal places to 18, so in our _mint function, we multiply 100,000 by 10 to the 18th power to mint a total of 100,000 tokens, each with 18 decimal places (similar to how 1 Eth is made up of 10 to 18 wei.) To deploy, we need to pass in the constructor values (name and symbol), so we can do the following in our deployment script: By extending the original ERC20 token, your token will inherit all of the following features and functionalities: Once deployed, you can use any of these functions to interact with your new smart contract. For another example of an ERC20 token, check out [Solidity by example)( https://solidity-by-example.org/app/erc20/) in conclusionOk, we covered a lot here, but for me this was the basics/core to get started with this stack, and it's something I want to have, not only as someone who is learning all this stuff, but also in the future if I need to reference anything I might need in the future. I hope you learned a lot. If you want to support multiple wallets in addition to MetaMask, check out Web3Modal, which makes it easy to implement support for multiple providers in your app with a fairly simple and customizable configuration. In my future tutorials and guides, I will dive deeper into more complex smart contract development and how to deploy them as subgraphs to expose GraphQL APIs on top of them and implement features like pagination and full-text search. I will also cover how to use technologies like IPFS and Web3 databases to store data in a decentralized manner. |
<<: The country's first digital RMB roadside parking scene was launched in Shenzhen
Everyone has moles on their body to a greater or ...
What does a passionate and philandering man look ...
As the saying goes, "Appearance is determine...
A woman's fate as seen from her physical feat...
On September 28, according to ChartBTC’s Twitter ...
There are indeed many poor people in the world to...
What do you think when you see the picture above?...
You can tell a person's life span by looking ...
You can tell whether a person is kind by looking ...
In life, more and more people don’t know how to r...
What is the creation line? What kind of influence...
In physiognomy, one can tell a person’s fate and ...
How to interpret a mole on a woman’s chin? In our...
On June 10, 2019, major cryptocurrency news site ...
Your facial complexion shows your fortune Facial ...