Getting Started with Web3

Riddhi Shree
7 min readSep 13, 2022

What would you need to get your hands dirty and to begin exploring Web3? A basic list of tools you can opt for, include npm, hardhat, dotenv, alchemy.com Chrome browser, and MetaMask.

Environment Setup

Create a free account on www.alchemy.com. Then, create an app in the desired network (e.g., Goerli, Rinkeby).

Download MetaMask from metamask.io and create a free account. I find it convenient using the MetaMask plugin for Chrome browser. In the MetaMask settings screen, click “Advanced” section, and enable “Show test networks” option. This will allow you to access the test networks (e.g., Goerli, Rinkeby). Metamask browser extension will allow connecting an Ethereum wallet to a Web3 application.

Create a working folder and install all of the required modules, as mentioned below:

npm init -y
npm install --save-dev hardhat
npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethersnpm install --save-dev dotenv

Initialise hardhat project, by running the following command and choosing the option “Create a JavaScript project”.

npx hardhat

Create a .env file in your working directory, and store sensitive values (locally only) in following format:

ALCHEMY_API_URL_WITH_KEY = ""
METAMASK_PRIVATE_KEY = ""

Obtain the Alchemy API URL from Alchemy dashboard page by selecting the desired app, and clicking on “VIEW KEY” button.

Follow this post to extract MetaMask private key.

Once you have obtained the secret values for your project, update the .env file.

Add the secret variables to the hardhat.config.js file, as explained here. For example:

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

module.exports = {
solidity: {
compilers: [
{
version: "0.8.0",
},
],
},
networks: {
goerli: {
url: process.env.ALCHEMY_GOERLI_API_URL_WITH_KEY,
accounts: [process.env.METAMASK_PRIVATE_KEY],
},
rinkeby: {
url: process.env.ALCHEMY_RINKEBY_API_URL_WITH_KEY,
accounts: [process.env.METAMASK_PRIVATE_KEY],
},
ganache: {
url: "http://127.0.0.1:7545",
network_id: "*",
},
},
};

Test your setup by running the command:

npx hardhat test

If compiler error is displayed complaining about the Solidity compiler version, then update hardhat.config.js file to reflect the correct compiler version.

...
solidity: {
compilers: [
{
version: "0.8.9",
},
],
},
...

Your working directory should now contain following files and folders:

Delete all files in contracts and test folders. Test your hardhat setup again.

Smart Contract

Solidity is a language that allows creating smart contracts. Create a new solidity file in “contracts” folder, having file extension as “.sol”. A sample of a smart contract is shown below:

// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.9;
contract Challenge3b {
// state variables
address seller;
string private name;
string private description;
uint256 price;
mapping(address => uint256 ) balances;
constructor() {
balances[seller] = 10;
}
// sell an article
function sellArticle(string memory _name, string memory _description, int256 _price) public {
seller = msg.sender;
name = _name;
description = _description;
price = uint256(_price);
if(int256(balances[seller]) - _price >= 0) {
balances[seller] -= price;
}
}
}

In the “scripts” folder, create a deploy.js file with following contents:

const main = async () => {
const [deployer] = await hre.ethers.getSigners();
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.address);
console.log("Account balance: ", accountBalance.toString());
// Rinkeby
const Challenge3b = await ethers.getContractFactory("Challenge3b");
const challenge3b = await Challenge3b.deploy();
await challenge3b.deployed();
console.log("Challenge-3b address: ", challenge3b.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();

Once the smart contract and the deployment scripts are ready, we can deploy the smart contract in a network of our choice. In current example, the above shown contract will be deployed to Rinkeby test network:

npx hardhat run scripts/deploy.js --network rinkeby

I had deployed multiple smart contracts using a single deployment file. Once the smart contracts were deployed successfully, their addresses were displayed on the terminal output:

MetaMask

MetaMask

Login to MetaMask account and select the desired network. Ensure sufficient funds are added to the selected account. Free ethers can be added to test accounts like Goerli and Rinkeby (soon to be deprecated) using various faucets. It is worth noting that only a limited amount can be added per day to any of the test accounts.

  1. https://goerlifaucet.com/
  2. https://rinkebyfaucet.com/

Web3 — Interacting with Smart Contracts

Create a new ReactJS project:

npx create-react-app web3-frontend-code
cd web3-frontend-code
npm start

Start a local server and navigate to http://localhost:3000/ in order to access the user interface.

Now, we will modify the code to add Web3 components. From the Hardhat project that was created earlier, copy the ABI files corresponding to your Smart Contracts.

Hardhat project’s folder structure

In my case, I copied the entire “artifacts/contracts” folder from the Hardhat project into the current project’s src folder.

ReactJS project’s folder structure

You may also refer to this detailed article on building a web3 frontend with React.

Replace the content of App.js file to connect to your MetaMask account and interact with your Smart Contracts. Example,

import "./App.css";
import abi3 from "./contracts/Challenge3.sol/Challenge3.json";
import { ethers } from "ethers";
function App() {
const contractABI3 = abi3.abi;
// Goerli Network
const contractAddress3 = "0xbBA226079cF0CE9b1149b298D8c636041D34235c";
const solve = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have MetaMask!");
return;
}
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
if (accounts.length !== 0) {
const account = accounts[0];
console.log("Connected to account: " + account);
}
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
// Challenge 3
const contract3 = new ethers.Contract(
contractAddress3,
contractABI3,
signer
);
await contract3.sellArticle("Toothbrush", "Don't forget to smile!", 1);
await contract3.sellArticle(
"getArticle",
"When you call me, say Z2l2ZU1lTW9yZQ==",
10
);
await contract3.sellArticle(
"Flag",
"Looking for something? Go get the article..",
1
);
} catch (error) {
console.log(error);
}
};
return (
<div className="App">
<header className="App-header">
<button className="btn waveButton" onClick={solve}>
Solve Web3 Challenge
</button>
</header>
</div>
);
}
export default App;

At this point, your new React application should look like this:

Ensure the console tab is visible, because all the magic is going to be visible here! When ready, click on the only visible button that says “Solve Web3 Challenge”. If you have the MetaMask plugin installed and configured in your browser, you should see a screen as shown below.

Click on “Next”. Then, click on “Connect”.

If connection was successful, you should see a success message in the console.

If ethers were required to complete any of the transactions with a smart contract, then MetaMask would ask you to confirm the transaction:

To view details of all successful transactions for a smart contract, you can visit etherscan.io and perform a search operation on the address of the smart contract, e.g., 0xbBA226079cF0CE9b1149b298D8c636041D34235c

If no results are displayed, click on the notification icon that says that the said address was located on a different chain.

Select your network. It’s Goerli Testnet in our case. All successful transactions should become visible.

Click on any of the hyperlinked transaction hashes (Txn Hash) to view transaction details.

Click on the link that says “Click to see More”.

The “Input Data” section could sometimes reveal sensitive information. Hence, it is worth spending some time here. Expand the “View Input As” dropdown and select “UTF-8

--

--

Riddhi Shree

Inquisitive by nature, I tend to drift towards things that are seemingly difficult, yet, interesting.