Token Balances, Web3 Woes, and React Rejoicing: A Trifecta of Tech Triumph

Token Balances, Web3 Woes, and React Rejoicing: A Trifecta of Tech Triumph

Step-by-step tutorial on creating a React application that gets the Ethereum address balances of the tokens that the address has in their balance. Here are the steps:

Step 1: Set up your development environment

Before we start, you will need to set up your development environment. Ensure that you have Node.js and npm installed on your computer. You can check if you have these installed by running the following commands in your terminal:

node -
npm -v        

If you don't have Node.js or npm installed, you can download them from the official website at https://nodejs.org.

Step 2: Create a new React project

The first step is to create a new React project. To do this, you can use the create-react-app command. Open your terminal and navigate to the directory where you want to create your project, and run the following command:

npx create-react-app my-app        

This will create a new React project called my-app. You can replace my-app with the name of your choice.

Step 3: Install required packages

Next, you need to install the required packages for this project. In your terminal, navigate to the root directory of your project and run the following command:

npm install web3 --save        

This will install the web3 library, which we will use to interact with the Ethereum blockchain.

Step 4: Create a new file for your code

Now that you have your project set up, you can start writing your code. In the root directory of your project, create a new file called App.js. This will be the main component for your application.

Step 5: Import necessary modules and define variables

In your App.js file, start by importing the necessary modules:

import React, { useState, useEffect } from 'react'
import Web3 from 'web3';
import './App.css';        

Next, define the following variables at the top of your file:

const infuraEndpoint = ''; // Replace YOUR_INFURA_ENDPOINT with your Infura endpoin
const etherscanApiKey = ''; // Replace YOUR_ETHERSCAN_API_KEY with your Etherscan API key
const abi = [
  {
    "constant": true,
    "inputs": [{ "name": "_owner", "type": "address" }],
    "name": "balanceOf",
    "outputs": [{ "name": "balance", "type": "uint256" }],
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "name",
    "outputs": [{ "name": "", "type": "string" }],
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "symbol",
    "outputs": [{ "name": "", "type": "string" }],
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "decimals",
    "outputs": [{ "name": "", "type": "uint8" }],
    "type": "function"
  }
];        

The infuraEndpoint variable should contain your Infura endpoint. You can sign up for a free account at https://infura.io. The etherscanApiKey variable should contain your Etherscan API key.

Step 7: The rest of the code

Update the fetchBalances function in the useEffect hook to fetch the token transfer events using the etherscanApiKey and the address state variable.

async function fetchBalances() { if (address === '') { return; } const web3 = new Web3(infuraEndpoint); const tokenTransferEventsUrl = `https://api.etherscan.io/api?module=account&action=tokentx&address=${address}&sort=desc&apikey=${etherscanApiKey}`; const response = await fetch(tokenTransferEventsUrl); const data = await response.json(); // ... }         

Extract the token addresses from the transfer events data by using a Set.

const tokenAddresses = new Set(data.result.map(tx => tx.contractAddress));         

Use web3.eth.getBalance to get the balance of the address in Ether.

const balanceEth = await web3.eth.getBalance(address);         

Create an empty array to store the token balances.

const balances = [];         

Add the Ethereum balance to the balances array.

balances.push({ tokenAddress: 'Native token', symbol: 'ETH', name: 'Ethereum', balance: balanceEth / 10 ** 18 });         

Loop through the token addresses and get the balance, symbol, name, and decimals of each token using the token contract ABI.

for (const tokenAddress of tokenAddresses) { const tokenContract = new web3.eth.Contract(abi, tokenAddress); const balance = await tokenContract.methods.balanceOf(address).call(); const symbol = await tokenContract.methods.symbol().call(); const name = await tokenContract.methods.name().call(); const decimals = await tokenContract.methods.decimals().call(); balances.push({ tokenAddress: tokenAddress, symbol: symbol, name: name, balance: balance / 10 ** decimals, }); }         

Set the balances state variable to the array of balances.

setBalances(balances);         

In the handleSubmit function, prevent the default form submission behavior using event.preventDefault(). Then, clear the balances state variable and set the address state variable to the value of the input field.

const handleSubmit = (event) => { event.preventDefault(); setBalances([]); setAddress(event.target.elements.address.value); }        

Step 8: Update App.css file

import React, { useState, useEffect } from 'react'
import Web3 from 'web3';
import './App.css';

const infuraEndpoint = ''; // Replace YOUR_INFURA_ENDPOINT with your Infura endpoint
const etherscanApiKey = ''; // Replace YOUR_ETHERSCAN_API_KEY with your Etherscan API key
const abi = [
? {
? ? "constant": true,
? ? "inputs": [{ "name": "_owner", "type": "address" }],
? ? "name": "balanceOf",
? ? "outputs": [{ "name": "balance", "type": "uint256" }],
? ? "type": "function"
? },
? {
? ? "constant": true,
? ? "inputs": [],
? ? "name": "name",
? ? "outputs": [{ "name": "", "type": "string" }],
? ? "type": "function"
? },
? {
? ? "constant": true,
? ? "inputs": [],
? ? "name": "symbol",
? ? "outputs": [{ "name": "", "type": "string" }],
? ? "type": "function"
? },
? {
? ? "constant": true,
? ? "inputs": [],
? ? "name": "decimals",
? ? "outputs": [{ "name": "", "type": "uint8" }],
? ? "type": "function"
? }
];

function App() {
? const [balances, setBalances] = useState([]);
? const [address, setAddress] = useState('');

? useEffect(() => {
? ? async function fetchBalances() {
? ? ? if (address === '') {
? ? ? ? return;
? ? ? }
? ? ? 
? ? ? const web3 = new Web3(infuraEndpoint);
? ? ? const tokenTransferEventsUrl = `https://api.etherscan.io/api?module=account&action=tokentx&address=${address}&sort=desc&apikey=${etherscanApiKey}`;

? ? ? const response = await fetch(tokenTransferEventsUrl);
? ? ? const data = await response.json();

? ? ? const tokenAddresses = new Set(data.result.map(tx => tx.contractAddress));
? ? ? const balanceEth = await web3.eth.getBalance(address);

? ? ? const balances = [];

? ? ? balances.push({
? ? ? ? tokenAddress: 'Native token',
? ? ? ? symbol: 'ETH',
? ? ? ? name: 'Ethereum',
? ? ? ? balance: balanceEth / 10 ** 18
? ? ? });

? ? ? for (const tokenAddress of tokenAddresses) {
? ? ? ? const tokenContract = new web3.eth.Contract(abi, tokenAddress);

? ? ? ? const balance = await tokenContract.methods.balanceOf(address).call();
? ? ? ? const symbol = await tokenContract.methods.symbol().call();
? ? ? ? const name = await tokenContract.methods.name().call();
? ? ? ? const decimals = await tokenContract.methods.decimals().call();

? ? ? ? balances.push({
? ? ? ? ? tokenAddress: tokenAddress,
? ? ? ? ? symbol: symbol,
? ? ? ? ? name: name,
? ? ? ? ? balance: balance / 10 ** decimals,
? ? ? ? });
? ? ? }

? ? ? setBalances(balances);
? ? }

? ? fetchBalances();
? }, [address]);

? const handleSubmit = (event) => {
? ? event.preventDefault();
? ? setBalances([]);
? ? setAddress(event.target.elements.address.value);
? }

? return (
? ? <div className="App">
? ? ? <h1>Address Balance Tracker</h1>
? ? ? <form onSubmit={handleSubmit}>


? ? ? ? ? <input type="text" name="address" placeholder='for ex. 0x000...000' />
? ? ? ? <button type="submit">Get Balances</button>
? ? ? </form>
? ? ? <div className="balances">
? ? ? ? {balances.length > 0 ? (
? ? ? ? ? balances.map((balance, index) => (
? ? ? ? ? ? <div className="balance" key={index}>
? ? ? ? ? ? ? <div className="token-name">{balance.name} ({balance.symbol})</div>
? ? ? ? ? ? ? <div className="token-balance">{balance.balance}</div>
? ? ? ? ? ? </div>
? ? ? ? ? ))
? ? ? ? ) : (
? ? ? ? ? <div className="no-balances">Enter an address to fetch token balances</div>
? ? ? ? )}
? ? ? </div>
? ? </div>
? );
}

export default App;        

Step 9: Make some styling.

Update App.css file

.App 
? background-color: black;
? color: white;
? font-family: Arial, sans-serif;
? display: flex;
? flex-direction: column;
? align-items: center;
}

.title {
? text-align: center;
? margin-top: 20px;
}

.balance {
? padding: 20px;
? margin: 20px;
? border: 1px solid white;
? border-radius: 5px;
? display: flex;
? flex-direction: column;
? align-items: center;
}

.token-name {
? font-weight: bold;
? color: yellow
}

.token-balance {
? color: pink
}

form {
? display: flex;
? flex-direction: column;
? align-items: center;
}

input[type="text"] {
? padding: 20px;
? border: 2px solid yellow
? border-radius: 5px;
? margin-top: 10px;
}

button {
? background-color: pink
? color: white;
? padding: 10px 20px;
? border: none;
? border-radius: 5px;
? margin-top: 10px;
}

.result {
? display: flex;
? flex-direction: column;
? align-items: center;
? margin-top: 20px;
}        

Run the application by typing the following command in your terminal:

npm start        

This should open up a browser window with the React application running. If you navigate to the address balance tracker page, you should see the form for entering an Ethereum address and a "Get Balances" button.

  1. Enter an Ethereum address that you want to track the token balances for and click the "Get Balances" button. The application will make API calls to Infura and Etherscan to retrieve the token balances for the entered address.
  2. Once the balances have been retrieved, they will be displayed in the list below the form. The list will show the name and symbol of each token, as well as the balance for that token.
  3. You can continue to enter new Ethereum addresses into the form and click the "Get Balances" button to track additional token balances.
  4. Congratulations! You have successfully created a React application that retrieves the token balances for an Ethereum address using Infura and Etherscan APIs.

In this tutorial, we covered the following steps:

  1. Set up a React project using Create React App.
  2. Install the required dependencies: Web3, Etherscan API key, and Infura API key.
  3. Create an Ethereum contract ABI to interact with the Ethereum blockchain.
  4. Define the state for the application, including the balances and the Ethereum address.
  5. Use the useEffect hook to make API calls to Infura and Etherscan to retrieve the token balances for the entered Ethereum address.
  6. Define the handleSubmit function to handle form submissions.
  7. Render the form and input field for entering the Ethereum address.
  8. Add the "Get Balances" button to the form.
  9. Render the balances list.
  10. Conditionally render the balances or a message to enter an Ethereum address.
  11. Add CSS styling to the application.
  12. Use dotenv to hide the sensitive API keys.
  13. Deploy the application to a hosting service, such as Netlify or Vercel.

Feel free to modify this application to fit your needs, such as adding additional functionality to track other Ethereum data or creating a different user interface. Happy coding!

要查看或添加评论,请登录

Aghasi Gasparyan的更多文章

社区洞察

其他会员也浏览了