0% found this document useful (0 votes)
7 views77 pages

Real-Time Blockchain Notifications

The document discusses the importance and implementation of real-time blockchain notifications, highlighting their role in enhancing security and user engagement within decentralized environments. It outlines the technologies used, including Alchemy Webhooks, Node.js, and React.js, which facilitate the creation of a dynamic notification system. The author, Shubhankar Banerjee, aims to empower readers by demystifying the complexities of integrating real-time notifications into blockchain applications.

Uploaded by

Tran Van Thuan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views77 pages

Real-Time Blockchain Notifications

The document discusses the importance and implementation of real-time blockchain notifications, highlighting their role in enhancing security and user engagement within decentralized environments. It outlines the technologies used, including Alchemy Webhooks, Node.js, and React.js, which facilitate the creation of a dynamic notification system. The author, Shubhankar Banerjee, aims to empower readers by demystifying the complexities of integrating real-time notifications into blockchain applications.

Uploaded by

Tran Van Thuan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 77

Real-Time Blockchain Notifications

Shubhankar Banerjee

All rights reserved. No part of this publication may be reproduced, distributed, or transmitted in
any form or by any means, including photocopying, recording, or other electronic or mechanical
methods, without the prior written permission of the publisher, except in the case of brief
quotations embodied in critical reviews and certain other noncommercial uses permitted by
copyright law. Although the author/co-author and publisher have made every effort to ensure
that the information in this book was correct at press time, the author/co-author and publisher do
not assume and hereby disclaim any liability to any party for any loss, damage, or disruption
caused by errors or omissions, whether such errors or omissions result from negligence,
accident, or any other cause. The resources in this book are provided for informational purposes
only and should not be used to replace the specialized training and professional judgment of a
health care or mental health care professional. Neither the author/co-author nor the publisher
can be held responsible for the use of the information provided within this book. Please always
consult a trained professional before making any decision regarding the treatment of yourself or
others.

Author/Co-Author – Shubhankar Banerjee


Publisher – C# Corner
Editorial Team – Deepak Tewatia, Baibhav Kumar
Publishing Team – Praveen Kumar
Promotional & Media – Rohit Tomar, Rohit Sharma

https://www.c-sharpcorner.com/ebooks/ 2
Educational background
Shubhankar completed a Bachelor of Computer Application (BCA) from PSIT College, affiliated
with Chhatrapati Sahu Ji Maharaj University Kanpur, in the year 2021. During his undergraduate
studies, he gained a strong foundation in computer science, including programming languages,
database management, and software development methodologies.
Building upon his undergraduate education, Shubhankar pursued a Master of Computer
Application (MCA) from MPEC College, affiliated with APJ Abdul Kalam University, Lucknow,
graduating in the year 2023. Throughout his master's program, he delved deeper into advanced
topics such as blockchain, artificial intelligence and machine learning. Additionally, he honed his
skills in software engineering principles and system architecture.
These academic pursuits have made him well-prepared to excel in professional roles within the
tech industry.

— Shubhankar Banerjee

https://www.c-sharpcorner.com/ebooks/ 3
Table of Contents:
Introduction to Real-Time Blockchain Notification System ............................................................... 5
Technologies to be Used ............................................................................................................... 7
Setting up your Alchemy App .......................................................................................................10
Building Server Infrastructure and Essential Endpoints ...................................................................16
Extending local server’s reach with ngrok ......................................................................................24
Creating a Webhook and connecting it with server logic .................................................................29
Designing the User-Interface (Part 1) ............................................................................................37
Designing the User-Interface (Part 2) ............................................................................................59

https://www.c-sharpcorner.com/ebooks/ 4
1
Introduction to Real-Time
Blockchain Notification
System

Overview

Welcome to the world of real-time blockchain notifications, in this


chapter, we will see the basics of real-time notifications, their
significance in the digital landscape, and their crucial role in enhancing
security within the blockchain ecosystem. Join us as we embark on this
empowering journey together.

https://www.c-sharpcorner.com/ebooks/ 5
Real-Time Notifications
Real-time notifications are instant alerts that provide users with immediate updates on critical
events within a system, ensuring timely awareness and engagement. They play a crucial role in
enhancing user experience by delivering information promptly as it unfolds. Real-time
notifications are set to transform the way users stay informed and interact with their activities.
These notifications aren't just alerts they provide user’s immediate insights into their in-app
activities. Real-time notifications have become essential in today's digital landscape where users
crave instant updates from their favorite apps. Think of this just like how your phone buzzes with
notifications from social media, banking apps, or even news alerts. Similarly, real-time
blockchain notifications provide timely updates about your blockchain activities, making your
journey more informed and secure.

Why we need Real-Time Notification in Blockchain


Now, let's talk about the blockchain environment. It’s a decentralized environment where every
move counts and security is a priority. Security in the blockchain is important due to its
decentralized structure, immutable ledger, and involvement in high-value transactions. The need
arises to safeguard against unauthorized access, manipulation, and potential exploits, ensuring
the integrity and privacy of the blockchain ecosystem.
How to get our dApps more secure then? Real-time notifications can enhance security in
blockchain by providing immediate alerts to users about any suspicious activities, unauthorized
access attempts, or irregular transactions. By enabling users to promptly respond to potential
threats, real-time notifications act as a proactive measure to mitigate risks and safeguard the
integrity of the blockchain ecosystem.
Despite their importance, only a handful of blockchain apps offer real-time notifications. Why?
Because handling them can be tricky. The complexities involved make it challenging for many
apps to provide this crucial feature.
Don’t worry. In this book, we're going to demystify the process and show you how to create real-
time dynamic notifications. As we embark on this journey together, our goal is simple – to
empower you. We'll break down the challenges, guide you through the complexities, and help
you take control of real-time notifications. Ready to make your blockchain experience more
dynamic? Let's dive in!

Setting the Stage


With the foundation laid we're diving into the world of real-time blockchain notifications, and I'm
here to make it super easy for you. Imagine this as the start of a cool adventure where my goal
is to help you understand and use blockchain notifications without any problems.
In the upcoming chapters, we'll break down all the tricky stuff about real-time notifications in
blockchain. It's like having a friendly guide showing you the ropes in a new place. We'll take on
the challenges, explain the important parts, and teach you how to create notifications that work
in real time. Think of it like getting instant alerts about important things happening in your
blockchain world.
Our plan is simple: cover the basics, talk about the techie stuff you need to know, and give you
hands-on examples so you can do it yourself. This isn't just about notifications; it's about giving
you the tools to take charge of your blockchain experience.
So, get ready for a fun ride as we explore this together. Whether you're a pro or a newbie
excited to dive into the world of blockchain notifications, our aim is clear – to make your
blockchain journey more interesting and easier. Ready to jump in? Let's start this awesome
journey together.

https://www.c-sharpcorner.com/ebooks/ 6
2
Technologies to be Used

Overview

In this chapter, we delve into the backbone of real-time blockchain


notifications. Our journey introduces Alchemy Webhooks, Node.js,
Express.js, Ether.js, Ngrok, MySQL Database, and React.js – the
driving forces behind our dynamic notification system. From capturing
blockchain events to crafting visually appealing interfaces, each
technology plays a crucial role in orchestrating seamless user
experiences. As we dissect these components one by one, prepare
to witness the symphony of innovation powering your blockchain
journey. Stay tuned for Chapter 3, where we embark on a deep dive
into Alchemy integration. Get ready to elevate your blockchain
experience to new heights!

https://www.c-sharpcorner.com/ebooks/ 7
Greetings again, readers. As we explore the amazing world of real-time blockchain notifications,
it is critical to understand the key technologies behind this dynamic journey. Let us look at the
key technologies that form the foundation of our real-time notification system.
During our technical journey, we came across important technological components such as
Alchemy Webhooks, Node.js, Express.js, ngrok, MySQL Database, and React.JS. These
technologies serve as the linchpins, orchestrating a symphony of real-time updates and
notifications, each playing a distinct role in ensuring a smooth and dynamic user experience.
Let’s look at these one at a time and understand about them.

Alchemy & Alchemy-Webhooks


In the world of blockchain, Alchemy stands as a comprehensive platform that provides a bridge
between developers and the blockchain infrastructure. It offers a suite of tools and services that
simplify the development and management of blockchain applications. Alchemy helps us to
interact with the blockchain without setting up a master node. You can simply think of Alchemy
as the backstage director, ensuring a seamless and efficient performance of blockchain
applications.
Moving forward Alchemy Webhooks is an integral component of Alchemy's tools that we are
provided. Alchemy Webhooks catches and sends real-time events within the blockchain. Some
of the key features of Alchemy Webhooks are as follows.

Key Features
• Event Capture: Alchemy Webhooks captures real-time events within the blockchain
ecosystem, ranging from transactions to account creations.
• Event Dispatch: Once captured, it swiftly dispatches these events, acting as the catalyst
for timely and dynamic notifications.
• Integration with Alchemy Dashboard: Alchemy Webhooks seamlessly integrates with
the Alchemy Dashboard, offering a user-friendly interface for developers to manage and
configure their webhook settings.
• Scalability: Notably, Alchemy Webhooks boasts the ability to monitor an impressive
50,000 addresses concurrently.

Node.js, Express.js and Ether.js


Now, let's shed some light on our powerhouse trio – Node.js, Express.js, and with the addition of
ether.js, together, they function as the dynamic architects behind our real-time blockchain
notification system, constructing a robust and efficient foundation.

Node.js
In our technological infrastructure, Node.js acts as the brainpower behind our operations. It
functions as the engine room, quietly handling server-side JavaScript, the coding language that
governs how our system behaves. In simpler terms, it processes instructions and ensures that
everything in our system runs smoothly. Think of it as the backbone, managing the core
functionalities of our notification system.

Express.js
Express.js serves as the meticulous coordinator of meeting points, commonly referred to as
endpoints. These are designated spots where different actions take place in our system.
Express.js organizes and manages these meeting points efficiently. Imagine it as the event
planner ensuring everything is in its place and runs seamlessly. It works together with Node.js to
make sure our system operates like a well-oiled machine.

https://www.c-sharpcorner.com/ebooks/ 8
Ether.js
We will be Ether.js is a specialized toolkit that plays a pivotal role by bestowing a touch of
enchantment upon our system, enabling seamless communication and interaction with the
Ethereum blockchain. It gives our system the capacity to understand, interact, and work
successfully with the complex language of the blockchain. This skill enables our system to
navigate the complexity of blockchain data with more ease.
To put it simply, ether.js acts as a bridge that allows our system to understand, interpret, and
communicate with the Ethereum blockchain.
using ethers.js package version 5.7.2.

Ngrok - Hosting the local server.


Ngrok functions as a hosting bridge, connecting our local server to the larger internet
environment. It acts as a channel, allowing our real-time notifications to reach individuals
globally. It's like a virtual postman delivering our alerts and ensuring they move throughout the
internet.
To put it simply, hosting is the act of placing something on the internet for others to see. Ngrok
functions as our helpful guide, taking our local server and putting it on the internet so that
everyone, no matter where they are, can see our real-time notifications. It's the secret sauce that
extends our alerts beyond our PC to the entire globe.
This is important in our real-time notification system because the Alchemy webhooks require a
get endpoint to which it will send the transaction data as a notification and to receive that we
need a hosted server with an active Get endpoint.

MySQL Database
The database functions as a digital administrator, keeping notifications that will be displayed to
users later. This structured method serves a key purpose: when a user wants to access
previous notifications, the database allows for quick and efficient retrieval.
Consider MySQL Database the unsung hero that secretly protects the integrity of our notification
data. Its job goes beyond simple storage; it serves as the backbone, ensuring that alerts are
safely stored for future reference.

React.js - The frontend designer


React.js specializes in turning our notifications into visually appealing and user-friendly
elements. The user interface it creates is not only useful but also visually appealing. Using
React.js, our users can engage with alerts more engagingly and seamlessly.
Simply said, React.js serves as the architect of a beautiful framework, ensuring that notifications
are both attractive and intuitive.

Summary
As we wrap up this chapter on the technologies steering your real-time blockchain notifications,
let's reflect on the powerhouses we've introduced – Alchemy Webhooks, Node.js, Express.js,
Ether.js, Ngrok, MySQL Database, and React.js. They're the backbone of your notification
system, working seamlessly to make your blockchain experience cutting-edge.
But hold on tight because the journey doesn't stop here. We're gearing up for the next chapter, a
deep dive into Alchemy. It's where we roll up our sleeves, sign up, and integrate Alchemy into
your blockchain applications. The stage is set for Chapter 3: Setting Up Alchemy - A Deep Dive.
We're not just scratching the surface; we're diving deep into the heart of blockchain integration.
Are you ready for the next leg of this thrilling journey? Let's keep the momentum going!

https://www.c-sharpcorner.com/ebooks/ 9
3
Setting up your Alchemy
App

Overview

In this chapter, we delve deeper into Alchemy, the powerhouse


simplifying blockchain development. We explore Alchemy Web3's role
as a bridge, freeing developers from technical complexities and
empowering innovation. Discover the significance of Alchemy RPC URL
and follow step-by-step instructions to create your first Alchemy app,
gaining access to seamless blockchain interactions. Do not miss the
chance to enhance your skills and explore further in Chapter 4, as we
build a Node.js server for hands-on experience in blockchain
management.

https://www.c-sharpcorner.com/ebooks/ 10
Welcome back, developers! In this chapter, we'll take a deep dive into Alchemy, the powerhouse
that simplifies the intricacies of working with blockchain, paving the way for seamless
development. We already learnt about Alchemy and Alchemy webhooks, but in this chapter we
will look at them in further depth. Let's look at some of the key words and steps you'll need to
get started with Alchemy and create an App.

Understanding Alchemy
Alchemy Web3 is a powerful platform that makes it easy for developers to build and interact with
blockchain applications. It acts as a bridge between our code and the blockchain network,
making the development process smoother and more efficient. It acts like a middleware for our
smart contract code and the blockchain network.
Today blockchain technology is revolutionizing how we handle transactions and data. Alchemy
Web3 steps in by simplifying the complexities of working with blockchain. This allows developers
to focus on creating their decentralized applications (dApps) without getting stuck down in the
technical details.

How Alchemy Works


Alchemy serves as a skilled facilitator, managing the complex operations behind the scenes,
allowing us the freedom to concentrate on developing the applications.
When sending transactions, Alchemy skillfully handles the details, ensuring secure and prompt
delivery of the transactions. If one requires specific data from the blockchain, it is also well-
equipped to retrieve the information we seek, removing the burden of navigating the
complexities.
What sets Alchemy apart is its ability to empower developers. One need not be a blockchain
expert to effectively use its capabilities. It levels the playing field by providing a full set of tools
and resources for developing creative apps, regardless of prior blockchain knowledge.

Alchemy RPC URL


RPC stands for Remote Procedure Call. In simple terms, it is an interface for one program to
request a service from another program on another computer, in this case, the blockchain
network. The RPC URL is the exact web address that allows your application to submit requests
to the blockchain network and get responses.
Alchemy provides a reliable and high-performance RPC URL for Ethereum, Polygon and many
other different blockchains. This URL is crafted to facilitate seamless interactions with the
blockchain, allowing us to access various functionalities such as sending transactions, querying
data, and listening to events.

Getting Started with Alchemy


Now, after learning how to use Alchemy, let's begin by signing up and creating our own Alchemy
API Key.
Let me guide you through the way of signing up with Alchemy and getting your API Key by
creating an Alchemy App. Follow the steps below.

Step 1. Visit Alchemy Home Page


Navigate to alchemy.com and click on the Sign-Up button at the top-right corner. If you already
have an Alchemy account, Sign in to your account.

https://www.c-sharpcorner.com/ebooks/ 11
Step 2. Sign Up in Alchemy
Sign Up and create an account in Alchemy directly using your Google account or any other
email, as per your wish.

Step 3. Visit your dashboard.


Log in to your Alchemy account, and you'll be able to access your personalized dashboard.

https://www.c-sharpcorner.com/ebooks/ 12
Step 4. Open apps tab
Click on the Apps button in the navbar on the left side to access the Apps window.

Step 5. Create a New App


Initiate the creation of your first app by clicking on the Create New App button.

https://www.c-sharpcorner.com/ebooks/ 13
Follow the prompts in the pop-up window, selecting the Chain and Network, assigning a unique
name, and providing a brief description.
Click on the Create app button to proceed.
Here, in this demo, I will be creating an app for the Polygon Testnet blockchain network and
name the app "Polygon_Mumbai".

Step 6. Get the RPC URL


Upon creating your app, navigate to the API key section by clicking on the API key button.

Here, you'll find your newly crafted RPC URL.

https://www.c-sharpcorner.com/ebooks/ 14
Congratulations! You've successfully forged an RPC URL, connecting you to the Polygon
Mumbai Testnet.
Repeat this process to create RPC URLs for different blockchain networks. But remember, a
maximum of 5 apps can be created on Alchemy.

Summary
In this chapter, we explored Alchemy's role as a powerhouse in simplifying blockchain
development. We learned how Alchemy Web3 acts as a bridge, freeing developers from
technical complexities and empowering them to focus on innovation. The Alchemy RPC URL
emerged as a key to seamless blockchain interactions.
Practically, we navigated the steps of signing up with Alchemy, creating our first app, and
obtaining the RPC URL for Polygon Mumbai Testnet. As we conclude, the journey continues in
Chapter 4, where we dive into building a Node.js server. Don't miss the chance to enhance your
skills and explore the intricacies of blockchain account and notification management. Join us in
the next chapter for a hands-on experience!

https://www.c-sharpcorner.com/ebooks/ 15
4
Building Server
Infrastructure and Essential
Endpoints

Overview

In this chapter, we delve into harnessing Node.js for a robust


blockchain notification system. It explores Node.js' efficiency for
real-time interactions, covering setup prerequisites and environment
configuration. Key steps include server building, endpoint
establishment, and functionalities like wallet creation, recovery,
balance fetching, webhook processing, and notification retrieval,
empowering developers for seamless implementation.

https://www.c-sharpcorner.com/ebooks/ 16
Welcome back, Developers! In our last chapter, we explored the important role of Alchemy in
simplifying blockchain development. Now, we focus on Node.js, the backbone of our real-time
notification system. n system. This chapter is dedicated to constructing our server and
establishing the essential endpoints that will play a pivotal role in shaping our future
developments.

Importance of Node.js in Blockchain Notification Systems


Node.js emerges as a powerful tool for our notification system due to its efficiency and event-
driven architecture, perfectly suited for handling blockchain interactions.

Prerequisites
Before we embark on our Node.js journey, let's ensure we have the essentials in place. Setting
up a development environment is a breeze with the right tools. Here's a quick overview:

Node.js Installation:
• Head over to nodejs.org.
• Click the LTS version for most users and follow the on-screen instructions to install
Node.js on your device.

NPM (Node Package Manager) Installation:


• To check if NPM is installed, open your terminal or command prompt and type -
npm -v //check npm version

• If you see a version number pop up, you're good to go.

Code Editor (e.g., Visual Studio Code) Installation:


• Visit code.visualstudio.com.
• Download and install Visual Studio Code (VSCode).
With Node.js, NPM, and VSCode installed, we're ready to start building our Node server.

Setting Up Development Environment


Now that our tools are lined up, let's organize our workspace. We will be initializing our node.js
server project and installing some npm libraries which will be needed in the development
process. Follow the steps below -

Step 1: Create a Project Folder


In your terminal, navigate to the desired location and type -

mkdir BlockchainNotifier_Server
cd BlockchainNotifier_Server

Congratulations! You've got your project ready with the name BlockchainNotifier_Server.

Step 2: Initialize a node.js project.


Next, after navigating to your project folder in the terminal type -

https://www.c-sharpcorner.com/ebooks/ 17
npm init -y //Initialize a node server

This command initializes a package.json file, which is like a project ID card. The -y flag saves us
from answering a bunch of questions making the process quick and easy.

Step 3: Installing Essential Packages


Installed the required packages.

npm install ethers [email protected] body-parser dotenv mysql2 //All-


important packages

Building a Node.js Server


Now that our workspace is organized, let's create the heart of our project – the main server file.

Step 1: Creating the main server file (e.g., server.js)


Create a JavaScript file in your working directory BlockchainNotifier_Server. You can name the
file server.js for simplicity.

Step 2: Setting Up the Express.js App


To define API routes, we need to set up the express app first.

const express = require('express');


const app = express(); //initialize express app

const PORT = 3000; //define the PORT on which the server has
to run

app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
//running script
});

Step 3: Start/Test your Node Server


Open your terminal, navigate to your project folder, and type:

node server.js

You should see a message saying your server is running.


With this we learned how to start our server. Next, we need to define some routes that are
needed for the project.

Define Routes and functionalities.


After setting the express app, we need to define the routes.
We need to create endpoints for basic functionalities that our Real-time Blockchain Notification
System will contain. The basic functionalities for which we need to create endpoints are -

• Creating Ethereum EOA Account Wallet


• Recovering Account using passphrase
• Fetching the Balance of the account

https://www.c-sharpcorner.com/ebooks/ 18
• Getting Webhook response and storing it in the database
• Endpoint to fetch notification.
Let’s create these endpoints one at a time.

Creating New Wallet


Our first endpoint is dedicated to the creation of Ethereum External Owned Accounts (EOA)
wallets. This functionality allows users to generate new Ethereum wallets, complete with a
mnemonic (passphrase), account address, and private key.
To create a new Ethereum Wallet we will be using the ethers.js package.
Import the ethers package in your server file.

const { ethers } = require('ethers');

After importing let’s start with creating the endpoint.

Endpoint:

app.get('/createAccount', async (request, response) => {


try {
const wallet = ethers.Wallet.createRandom();

let newWallet = {
"message": "Success",
"Mnemonic": wallet.mnemonic.phrase.toString(),
"Address": wallet.address.toString(),
"PrivateKey": wallet.privateKey.toString()
}

response.send(newWallet);
}
catch {
result = {
"message": "error"
}
response.send(result)
}

});

Here, we are defining an endpoint named “createAccount” whenever a client endpoint hits this
endpoint. A JSON object containing wallet address, private key and passphrase will be returned.
Using this endpoint we can create new Ethereum wallets.
The createAccount endpoint uses a predefined method present in the ethers package named
createRandom to generate random wallets.

Recovering Wallet using Passphrase


The ability to recover an account is a fundamental aspect of user convenience and security. This
endpoint enables users to recover their accounts using a passphrase. Whether a user has
forgotten their details or is accessing their account from a new device, this functionality ensures
a smooth and secure account recovery process.

https://www.c-sharpcorner.com/ebooks/ 19
Endpoint:

// recover account from mnemonic


app.post('/recover/mnemonic/:Mnemonic', async (request, response) => {
try {
let mnemonic = request.params.Mnemonic;

// Create a wallet instance from the provided mnemonic


const wallet = ethers.Wallet.fromMnemonic(mnemonic);
// Retrieve the Ethereum address and private key
const address = wallet.address;
const privateKey = wallet.privateKey;
result = {
"message": "Success",
"Mnemonic": mnemonic,
"Address": address,
"PrivateKey": privateKey
}
response.send(result);
}
catch {
result = {
"message": "error"
}
response.send(result)
}
});

Here, we are defining an endpoint named “/recover/mnemonic” which is taking a parameter


Mnemonic and recovering the wallet using the fromMnemonic method present inside ethers
package. This endpoint returns a JSON result with the recovered wallet’s passphrase, address,
and private key.

Fetching Balance of the Account


This endpoint opens the door to real-time balance updates for user accounts. By querying this
endpoint, users can retrieve the current balance associated with their Ethereum account.
Endpoint:

//Fetch Balance of an Ethereum Account


app.post('/balance', async (request, response) => {
try {
let rpc = request.query.RPC;
let address = request.query.address;

const provider = new ethers.providers.JsonRpcProvider(rpc);


balance = await provider.getBalance(address);
balanceInEthers = await ethers.utils.formatEther(balance);

let networkDetails = {
"message": "Success",

https://www.c-sharpcorner.com/ebooks/ 20
"balance": balanceInEthers.toString()
};
response.send(networkDetails);
}
catch {
result = {
"message": "error"
}
response.send(result)
}
});

Here, we are defining the endpoint with the name “/balance” which takes two parameters RPC
URL of the network on which balance is to be checked and wallet address whose balance is to
be checked.

Getting Webhook Response and Storing in Database


Real-time updates are the heart of our notification system, and this endpoint plays a central role.
It captures and processes the response generated by the webhook when a transaction occurs
for a specified address. The processed information is then stored securely in our database,
forming the foundation for real-time notifications.
We will be using the body-parser package and mysql package for reading the webhook
response and storing them. Import the packages.

const mysql = require('mysql2');


const bodyParser = require('body-parser');

Next, we need to connect to the database.

Pre-requisites
• Your device should have MySQL database installed.
• Create a database with any name you desire and, in that database, create an empty
table with columns such as notification_Id (type: integer), userAddress (type: varchar),
notification_msg (type: varchar), isRead (type: boolean).
Once you are ready with the database, then let’s connect the server with the database.

// Database connection details


// Replace these values with your actual database connection details
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'Your_Password',
database: 'Your_database_name'
})
// connect to db
connection.connect((err) => {
if (err) {
console.error('Error connecting to MySQL:', err);
return;

https://www.c-sharpcorner.com/ebooks/ 21
}
console.log('Connected to MySQL database');
});

Here, we are providing the connection details for our database and then connecting using the
connection string.
We also need to enable our app to use JSON parser middleware to parse the JSON which will
be provided by the webhook inside the request body.

// Middleware to parse JSON request bodies


app.use(express.json());

Now, we are ready to define an endpoint where we will be receiving the webhook data.

Endpoint:

//Receive Webhook data and store in database


app.post('/webhook', (req, res) => {
let userAddress = req.body.event.activity[0].toAddress;
let userMessage = `You received ${req.body.event.activity[0].value}
${req.body.event.activity[0].asset} from
${req.body.event.activity[0].fromAddress}`;

// Store the data in the database


const query = 'INSERT INTO notification (userAddress,
notification_msg, isRead) VALUES (?,?,?)';
const values = [userAddress, userMessage, false];
connection.query(query, values, (err, results) => {
if (err) {
console.error('Error inserting data into MySQL:', err);
res.status(500).json({ error: 'Internal Server Error' });
return;
}
});

// Send a response (optional)


res.json({ status: 'Received the webhook payload' });
});

Here, an endpoint “/webhook” is defined to receive the JSON data from the Alchemy Webhook
whenever a transaction occurs on a particular address provided in the webhook.
In this, we are taking the user address from the JSON object withthe key toAddress. It means
that the wallet address who will be in the receiving end will get the notification generated, and
the notification msg is created using the amount and sender’s address.
After that, I insert the generated notification into the notification table that is present in my
database.

Fetch Notification from the database.


The final piece of the puzzle is the endpoint dedicated to fetching notifications. This functionality
allows users to retrieve stored notifications from the database.

https://www.c-sharpcorner.com/ebooks/ 22
After connecting the server app with the database and storing the notifications, it’s now time to
fetch those notifications on the basic of the user address.
Endpoint:

//Fetch the Notification from Databaseon the basis of useraddress


app.get('/notifications/:userAddress', (req, res) => {
const userAddress = req.params.userAddress;

// Query to fetch notifications for a given userId


const query = 'SELECT * FROM notification WHERE userAddress = ?';
connection.query(query, [userAddress], (err, results) => {
if (err) {
console.error('Error fetching notifications from MySQL:',
err);
res.status(500).json({ error: 'Internal Server Error' });
return;
}
let finalResult = {
status: true,
result: results
}
res.setHeader('Content-Type', 'application/json');

res.send(finalResult);
});
});

Here, we are defining an endpoint with the name “/notification” which takes a parameter
userAddress and fetches the notification from the database based on userAddress.

Summary
In this chapter, we harnessed the power of Node.js to construct a robust server for our real-time
blockchain notification system. Essential endpoints were created, enabling functionalities like
wallet creation, account recovery, balance fetching, webhook response processing, and
notification retrieval. The practical guide empowers developers to implement these features
seamlessly. As we conclude, dive into Chapter 5, where we extend the system's reach with
ngrok for global accessibility. The journey continues -- happy coding!

https://www.c-sharpcorner.com/ebooks/ 23
5
Extending local server’s
reach with ngrok

Overview

In this chapter, we address the necessity of extending our local


Node.js server globally for real-time blockchain notifications.
Temporary hosting, exemplified by ngrok, provides a solution without
long-term commitments. We delve into the installation, configuration,
and limitations of ngrok, emphasizing its role in showcasing local
server functionalities on a global scale.

https://www.c-sharpcorner.com/ebooks/ 24
Welcome back, Developers! In our last chapter, we learned how to start our own Node.js server
to capture real-time events from the blockchain. We also created the important endpoints that
we will need in the project. Lastly, we also learned how to connect our server with the database.
In this chapter we will be learning how to extend the reach of the local node server that we
created globally, using a handy tool called ngrok. But first let’s look at why we need temporary
hosting.

Understanding the Need Behind Temporary Server Hosting


In our journey of developing a real-time blockchain notification system, we face a challenge – we
want to receive the notification activities from the blockchain behind the scenes and show it to
the users after filtering. That's where temporary server hosting is needed Think of it as setting up
a stage for a special event; you wouldn't build something permanent for just one show, right?
Similarly, in development, we need a way to flaunt our real-time notifications globally for a
certain amount of time without making a long-term commitment.

Why do we need this temporary hosting?


In the world of Alchemy Webhook, we need to pass a URL to get the Webhook response. If that
URL is local, the webhook notifications that Alchemy would send us won't get received and the
notifications can't be generated. That's where ngrok comes in, helping us create a temporary
server – a virtual stage for our real-time notifications to work.
So, consider ngrok as a spotlight that illuminates exclusively for our event, rendering our local
server visible globally. Stay with us as we uncover how to use ngrok to host our server
temporarily.

Installing and Configuring Ngrok


Let's start our journey of hosting our server.
The first step is to Install ngrok on your local system. To install ngrok to your local system follow
the steps given below:

Step 1: Head over to the ngrok download website from where we will be downloading ngrok -
https://ngrok.com/download.

Step 2: Find the download section, and depending on your operating system, grab the right
version.

Step 3: Once downloaded, unzip the file to reveal the ngrok executable file. There will be a file
with a .exe extension.

After installing, let's check if ngrok is correctly installed or not.

Step 4: To check the correct ngrok installation. Open your terminal or command prompt.
Navigate to the folder where you unzipped ngrok and type ngrok. Some basic information should
pop up on your screen.

https://www.c-sharpcorner.com/ebooks/ 25
Step 5: Add the auth-token to the default ngrok.yml file. To do that in the same terminal run the
command.

ngrok config add-authtoken <your-auth-token>

To get your auth token sign up on ngrok https://dashboard.ngrok.com/signup


With this, we have successfully installed ngrok on our local system.
Let’s now look at how we can look at how we can host our local host port to the global network.

Configuring ngrok with node server


After we successfully installed ngrok to our local system. It's now time to look at how we can
host our node server. Here's a quick guide to go through, after this, we will be hosting the node
server that we created in our previous article.

Running a node server globally


Step 1: Open a new terminal window.

Step 2: Navigate to the directory where your Node.js server file is located.

Step 3: Make sure your Node server is running – if not, start it up with node [your_server_file.js].

Step 4: Open a new terminal.

Step 5: Navigate to the folder where your ngrok executable file is present.

Step 6: Type - ngrok http [your_local_port] (replace [your_local_port] with your actual local
server port, for eg.,3000 for Node.js).

Step 7: Congratulations! Ngrok now generates a public URL for your local server. Use that URL
to access your server and server-side APIs.

https://www.c-sharpcorner.com/ebooks/ 26
With this, whenever there is a request on the ngrok server it gets forwarded to your local host
server and the response is then returned to the user.

Flexibility and Ease of Use


Ngrok keeps it simple. It doesn't demand complex setups or tech acrobatics. It’s like having a
backstage crew that effortlessly sets the stage for your server. The flexibility to expose your
server temporarily is precisely what we need for development.
With all this, now we have hosted our local server on a temporary global server.
Now, Let's look at the limitations.

Limitations of Free Server Hosting


While free server hosting options like ngrok are fantastic for getting a taste of global exposure,
it's crucial to be aware of their limitations. Let's look at the restrictions which come along with
ngrok free hosting:

Single User
Only one user can access the free plan making it great for personal projects but not ideal for
large-scale performances.

Single Active Endpoint


You're limited to one active endpoint. The constraint of being limited to one active endpoint
implies that users can only establish a single-entry point for external access to their local server.
An "endpoint" here refers to a specific route or URL that external entities can use to interact with
the hosted application. This limitation is similar to having just one doorway for the audience to
enter an event. While this is suitable for straightforward setups or less complex applications, it
could present challenges for more intricate projects that may require multiple entry points for
various functionalities or services.

Ngrok Static Domain


The free plan provides only one ngrok static domain. This means your server gets a single,
unchangeable address. For some projects, this is perfect but for others, it may limit flexibility.

Bandwidth up to 1GB per month


The restriction of 1 GB of outgoing bandwidth per month implies that users can transfer a
maximum of 1 GB of data from their local server to external sources within a given month.
Exceeding the 1 GB limit might affect the performance of the global application. It could lead to
potential delays, data congestion, or interruptions.

Connection Rate of 120 connections/min

https://www.c-sharpcorner.com/ebooks/ 27
TCP connection rate of 120 per minute signifies that users can establish a maximum of 120
Transmission Control Protocol (TCP) connections per minute. This means only 120 connections
can be made per minute.

Summary
In this chapter, we explored the necessity of extending the reach of our local Node.js server
globally for a real-time blockchain notification system. Temporary hosting becomes essential to
showcase these notifications without a long-term commitment. Ngrok, our tool of choice, acts as
a virtual stage, making our local server globally visible. The chapter covers the installation and
configuration of ngrok, emphasizing the importance of a secure authentication token.
Readers learn step-by-step procedures, from downloading ngrok to configuring it with their
Node.js server. The process involves running the Node server globally using ngrok, generating a
public URL for global access. The chapter concludes by highlighting the flexibility and simplicity
of ngrok, noting its role as a backstage crew effortlessly setting the stage for global server
exposure.
Moving on to chapter 6, now we will be creating a webhook to track the address activity and
move forward with the notification generation.

https://www.c-sharpcorner.com/ebooks/ 28
6
Creating a Webhook and
connecting it with server
logic

Overview

In this Chapter, we delve into Alchemy Webhooks, pivotal tools for


streamlined communication between our Node.js server and the
dynamic blockchain. We explore their efficiency in handling events
and facilitating real-time communication. The focus is on Address
Activity webhooks, tracking transactions across various tokens. We
learn to set them up using both the Alchemy Dashboard and API,
ensuring seamless integration into blockchain applications.

https://www.c-sharpcorner.com/ebooks/ 29
Welcome back, Developers! In our previous chapter, we set out on a journey to extend the
global reach of our local Node.js server using an effective tool called ngrok. We created a virtual
stage, temporarily hosting our server for the world to witness the real-time blockchain
notifications. Using this we can easily receive the notification for any transaction update for a
particular address.
In this chapter, we look at Alchemy Webhooks, and learn how we can create a webhook using
the Alchemy dashboard as well as API.

Understanding Alchemy Webhooks


Alchemy Webhooks act like vigilant messengers, strategically placed to catch important
moments in the blockchain. Their main job is to act as triggers, responding to big events like
transactions. These webhooks are crucial in making sure our server talks efficiently and quickly
with the blockchain. Some benefits that Alchemy webhooks provide.

Efficient Handling of Events


Unlike the usual way of servers repeatedly asking for updates, Alchemy Webhooks works
smartly. They only talk to our server when something important happens, skipping the constant
checking. This clever approach means our server stays informed without bothering the
blockchain too much, making the process of handling events super-efficient.

Making Real-Time Communication Easy


Alchemy Webhooks shine in their knack for creating direct and real-time communication
between Alchemy and our Node.js server. When transactions happen on the blockchain, these
webhooks instantly send notifications. This ensures our server always knows what's happening,
keeping it in sync with the ever-changing world of the blockchain. This direct link makes sure our
server and the blockchain work together smoothly.
Alchemy provides different types of Webhooks. We will be now discussing one of the types of
webhooks- Address activity webhook that we will be using for our notifications.

Address Activity Webhook


The Address Activity webhook is a dynamic feature that tracks all transfers involving ETH,
ERC20, ERC721, and ERC1155 tokens. Its primary function is to provide real-time state
changes whenever an address sends or receives tokens or ETH. This powerful tool allows
developers to specify up to 50,000 addresses to track within a single webhook, making it a
versatile solution for a wide range of applications.

Types of Transfers
Address Activity webhook captures three main types of transfers:

• External ETH: Represents top-level transactions from an Externally Owned Account


(EOA).
• Token Transfers: Involves event logs for ERC20, ERC721, and ERC1155 token
transfers.
• Internal ETH Transfers: Captures internal transfers originating from a smart contract
address.

Supported Networks
Alchemy's Address Activity webhook supports both Mainnet and Testnet environments across
multiple blockchain networks, ensuring flexibility in development and testing.

https://www.c-sharpcorner.com/ebooks/ 30
Chain Mainnet Testnet
Ethereum
Polygon
Optimism
Arbitrium
Base ; no internal transaction support ; no internal transaction support

Example Response
Upon a tracked address engaging in token or ETH transactions, the webhook provides a
response, detailing the event's essential information. This includes data such as the transaction
block number, hash, involved addresses, transferred value, token details, and more. The
response is provided in a JSON format like -

{
"webhookId": "wh_k63lg72rxda78gce",
"id": "whevt_vq499kv7elmlbp2v",
"createdAt": "2024-01-23T07:42:26.411977228Z",
"type": "ADDRESS_ACTIVITY",
"event": {
"network": "ETH_MAINNET",
"activity": [
{
"blockNum": "0xdf34a3",
"hash":
"0x7a4a39da2a3fa1fc2ef88fd1eaea070286ed2aba21e0419dcfb6d5c5d9f02a72",
"fromAddress": "0x503828976d22510aad0201ac7ec88293211d23da",
"toAddress": "0xbe3f4b43db5eb49d1f48f53443b9abce45da3b79",
"value": 293.092129,
"erc721TokenId": null,
"erc1155Metadata": null,
"asset": "USDC",
"category": "token",
"rawContract": {
"rawValue":
"0x0000000000000000000000000000000000000000000000000000000011783b21",
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"decimals": 6
},
"typeTraceAddress": null,
"log": {
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"topics": [

"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",

"0x000000000000000000000000503828976d22510aad0201ac7ec88293211d23da",

"0x000000000000000000000000be3f4b43db5eb49d1f48f53443b9abce45da3b79"

https://www.c-sharpcorner.com/ebooks/ 31
],
"data":
"0x0000000000000000000000000000000000000000000000000000000011783b21",
"blockNumber": "0xdf34a3",
"transactionHash":
"0x7a4a39da2a3fa1fc2ef88fd1eaea070286ed2aba21e0419dcfb6d5c5d9f02a72",
"transactionIndex": "0x46",
"blockHash":
"0xa99ec54413bd3db3f9bdb0c1ad3ab1400ee0ecefb47803e17f9d33bc4d0a1e91",
"logIndex": "0x6e",
"removed": false
}
},
{
"blockNum": "0xdf34a3",
"hash":
"0xc84eeeb72d2b23161fd93b088f304902cbd8b4510f1455a65fdac160e37b3173",
"fromAddress": "0x71660c4005ba85c37ccec55d0c4493e66fe775d3",
"toAddress": "0x7853b3736edba9d7ce681f2a90264307694f97f2",
"value": 2400,
"erc721TokenId": null,
"erc1155Metadata": null,
"asset": "USDC",
"category": "token",
"rawContract": {
"rawValue":
"0x000000000000000000000000000000000000000000000000000000008f0d1800",
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"decimals": 6
},
"typeTraceAddress": null,
"log": {
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"topics": [

"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",

"0x00000000000000000000000071660c4005ba85c37ccec55d0c4493e66fe775d3",

"0x0000000000000000000000007853b3736edba9d7ce681f2a90264307694f97f2"
],
"data":
"0x000000000000000000000000000000000000000000000000000000008f0d1800",
"blockNumber": "0xdf34a3",
"transactionHash":
"0xc84eeeb72d2b23161fd93b088f304902cbd8b4510f1455a65fdac160e37b3173",
"transactionIndex": "0x48",

https://www.c-sharpcorner.com/ebooks/ 32
"blockHash":
"0xa99ec54413bd3db3f9bdb0c1ad3ab1400ee0ecefb47803e17f9d33bc4d0a1e91",
"logIndex": "0x74",
"removed": false
}
}
]
}
}

The response data provided above is a dummy response, which tells us the format and keys
that the response object from webhook will contain.
Now, as we have learned about Address activity webhook, let’s now learn how to create it.

Setting Up of Address Activity Webhook


Setting up an address activity webhook is a simple task. But before creating that we need to
ensure something first.

Pre-requisites
• Should have an Alchemy account.
• Should have the blockchain network App created before trying to create the webhook for
that blockchain network.
After ensuring the pre-requisites that are needed, we are set to begin with the creation of
address activity webhook.
We can create address activity webhook using two methods.

• Using Alchemy Dashboard


• Using API

We will discuss both methods one after another.

Using Alchemy Dashboard


Follow the steps given below to set up the address activity webhook using the alchemy
dashboard user interface.

Step 1: In your Alchemy Dashboard click the Webhooks tab present on the left navbar.

https://www.c-sharpcorner.com/ebooks/ 33
Step 2: Find Address Activity and click the CREATE WEBHOOK button on the right side of the
window.

Step 3: Select your CHAIN in the dropdown. Then choose your NETWORK. Remember that
there should be an App created for the Chain and Network you choose.

Step 4: Paste your unique webhook URL into the WEBHOOK URL field. In our case it will be
the ngrok global URL that we learned to generate in the previous chapter followed by the
/webhook endpoint as it is the dedicated endpoint, we designed to handle the webhook
response. For example: “ https://cfe7-182-156-224-114.ngrok-free.app/webhook “
Remember, the ngrok URL is temporary and you need to modify the URL for the webhook if it is
closed as every time starting the hosting, will generate new URL.

Step 5: Enter your ETHEREUM ADDRESSES that need to be monitored. Remember that
webhook response will be generated for only those addresses who are added to the Addresses
to be monitored.

Step 6: Click CREATE WEBHOOK. Your webhook is created and appears in the list.
With this we have successfully created a webhook. Now moving forward let’s take a look at how
to create a webhook using Api.

Using Alchemy API


Creating Address Activity Webhook using Alchemy API is a simple task. So, we will now be
creating an address activity webhook using Alchemy Api endpoint.
This method can be helpful for large dApps where we need to monitor more than 50,000
addresses. If the address count reaches 50,000, we can create a mechanism which can
automatically check the address count in the created webhook and if it is full then can create a
new webhook using the API call.
Follow the Steps below to create an Address-Activity webhook using Alchemy API.

Step 1: Install axios package which will help us to post a request to the Alchemy Servers.

npm install axios // Install AXIOS package

Step 2: Add the requirement for Axios and dotenv package which we have already installed
earlier.

// Include AXIOS to call webhook API


const axios = require('axios');
// Include dotenv

https://www.c-sharpcorner.com/ebooks/ 34
require("dotenv").config();

Step 3: Create a file named dotenv(.env) in your project folder and store your Alchemy
Webhook Token or AlchemyXToken in the env file.
To get the Alchemy Token visit the Webhook page in your Alchemy dashboard which I
mentioned while discussing how to create Webhook using the dashboard interface earlier. There
at the top right corner, you will find your Alchemy Auth-Token

Step 4: Create the Endpoint to Create Webhook.

app.post('/create-webhook', async (req, res) => {


try {
// Fetch Alchemy Webhook Token from .env Config
const XAclechyToken = process.env.AlchemyWebhookToken;

const requestData = {
network: req.body.WebhookNetwork,
webhook_type: "ADDRESS_ACTIVITY",
webhook_url: req.body.WebhookURL,
addresses: req.body.WebhookAddress
}
const response = await
axios.post("https://dashboard.alchemy.com/api/create-webhook/", requestData, {
headers: {
"Accept": "application/json",
"X-Alchemy-Token": XAclechyToken,
"Content-Type": "application/json"
}
});

// Check if the request was successful


if (response.status !== 200) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

// Handle success
const responseBody = {
message : "Webhook Created",
response : {

https://www.c-sharpcorner.com/ebooks/ 35
Webhook_Id : response.data.data.id,
}
}
res.status(200).send(responseBody);
} catch (error) {
// Handle errors
res.status(500).json({ error: error.message });
}
});

Here, as webhook_url you need to paste your unique webhook URL. In our case it will be the
ngrok global URL that we learned to generate in the previous chapter followed by the /webhook
endpoint as it is the dedicated endpoint, we designed to handle the webhook response. For
example: “ https://cfe7-182-156-224-114.ngrok-free.app/webhook “.
Provide the Address to be added to the webhook in the form of a string array and the network on
which you want to create the webhook. You can choose whichever network you want and then
use the network name convention that Alchemy supports. You can find the Networks and
naming convention that Alchemy supports at https://docs.alchemy.com/create-webhook

And lastly you will be getting the webhook Id of the newly created Webhook. You can store it in
a database table for future use. Using the Webhook Id you can Add/Remove wallet addresses to
it. With this, we have learned how to create an Address-Activity Webhook using the dashboard
as well as alchemy API.

Summary
In this chapter, we explored the world of Alchemy Webhooks and discovered their critical role in
enabling smooth communication between our Node.js server and the dynamic blockchain.
Alchemy Webhooks' quick event processing and real-time communication features guarantee
that our server remains aware of critical transactions while avoiding excessive data retrieval. We
investigated the dynamic features of the Address Activity webhook, such as tracking
transactions through ETH, ERC20, ERC721, and ERC1155 tokens. The chapter concluded with
a practical tutorial to configure the Address Activity webhook using both the Alchemy Dashboard
and the API. We walked developers through the procedures to ensure they could smoothly
integrate this powerful technology into their blockchain apps.
Moving forward we will continue our exploration further into the realm of user interfaces with the
next chapter in line.

https://www.c-sharpcorner.com/ebooks/ 36
7
Designing the User-
Interface (Part 1)

Overview

In this chapter. We will explore the power of React.js for crafting


dynamic user interfaces in our blockchain notification system. Learn
why React.js is chosen, its declarative syntax, component-based
architecture, and efficient Virtual-DOM. Follow step-by-step
instructions to set up a React project and design essential pages
like Home, Create Wallet, and Recover Wallet. Enhance user
engagement with intuitive interfaces reflecting blockchain's
innovation. Elevate your project's UI/UX for a seamless user
experience.

https://www.c-sharpcorner.com/ebooks/ 37
Welcome back, Developers! In the previous chapter, we learned about an effective tool to work
as the base for our real-time blockchain notification-Alchemy Webhooks and learned how to set
up these webhooks to receive notifications. With this, we have completed the server side of our
blockchain Notification. But now that doesn't mean that there won’t be a need for any
modifications. Feel free to add new features according to your wish.
In this chapter, we'll look at how we can create user interfaces that work smoothly with our
project. A well-designed interface is more than just an aesthetic element; it serves as the entry
point for a user's engagement with the dynamic world of blockchain transactions.
Blockchain's decentralized and transparent nature requires a user interface that reflects its
innovation. We will be creating a basic User-Interface for you to understand it well, but you are
free to create a more appealing UI/UX as you wish.

Why React.js for Real-time Blockchain Notifications


In the dynamic landscape of web development, React.js stands as a excellent choice for crafting
the user interface of our real-time blockchain notification system. React, developed by
Facebook, is a JavaScript library that excels in building interactive and responsive UIs with
efficiency and clarity.
The advantageous features that made us choose React as the frontend designing technology -

• React Declarative Syntax


• Component-Based Architecture
• Efficient Virtual-DOM
• React Native for Cross-Platform Compatibility
• Ecosystem for Community Support
Now after getting why we choose React as the front-end developing tool. Let’s now start with it.

Creating your react project.


To create an empty, React App follow the steps below -

Step 1: Install Node.js and npm


Before diving into React development, ensure that Node.js and npm (Node Package Manager)
are installed on your machine. These tools are fundamental for managing dependencies and
running JavaScript applications.

Step 2: Install Create React App


Execute the following command in your terminal to install Create React App globally:

npm install –g create-react-app // Install create-react-app package globally

Step 3: Initialize a React Project


Create a new React project by running the following command:

npx create-react-app blockchain-notificationUI // Initialize a React Project

By running these commands, a new React-app will be created. In the terminal type

npm start // Start the React App

This will start the app and a react template will be displayed in your browser.

https://www.c-sharpcorner.com/ebooks/ 38
Creating First Page
After you have initialized a new project, let’s start creating the first page which should be our
Home page.
Inside the src folder create a new folder named “Components”. Here we will be keeping all our
Components i.e. (JavaScript and CSS files).

Now after creating the file define how the component should look.
The first page should be telling the users about the wallet with 2 buttons, one to create a new
account and other to recover the account in it. The Home_page.js file looks like this:

// Home_page.js
import React from "react";
import logo from '../../Images/yourCryptoLogo-removebg-preview.png';
import ethereumLogo from "../../Images/ethereumLogo.png";
import polygonLogo from "../../Images/polygonLo.png";
import avalancheLogo from "../../Images/avalancheLogo.png";
import solanaLogo from "../../Images/solanaLogo.png";
import '../HomePageComponent/CSS/Home_page.css';
import { useNavigate } from "react-router-dom";

function Home_page() {

const navigate = useNavigate();

function ClearLocalStorage() {
localStorage.clear()
}

const openRecover = () => {


navigate("/recover-wallet")
}

const openCreate = () => {


navigate("/create-wallet")
}

return (
<div>
<ClearLocalStorage />
<div className="backcard">
<div className="logo center-align">

https://www.c-sharpcorner.com/ebooks/ 39
<img src={logo} alt='Wallet' className="logoImage" />
</div>

<div className="top-align"><h4 className="center-align">YourCrypto Wallet


welcomes you</h4>
</div>
<div className="center-align start-guide-text">To start with YourCrypto
Wallet, create a new account or import an existing one</div>
<div className="start-guide-text center-align"><b>Supports: </b></div>
<div className="support-logo center-align">
<img src={ethereumLogo} alt='Wallet' className="support-logoImage" />
<img src={polygonLogo} alt='Wallet' className="support-logoImage" />
<img src={avalancheLogo} alt='Wallet' className="support-logoImage" />
<img src={solanaLogo} alt='Wallet' className="support-logoImage" />
</div>
<div className="button-container">
<button type='button' className="btn btn-primary set-button center-
align" onClick={openCreate}>Create new account</button><br />
<button type='button' className="btn btn-primary set-button center-
align" onClick={openRecover}>Recover Account</button>
</div>
</div>
</div >
);
}

export default Home_page;

This JS file uses some custom CSS and bootstrap CSS. To add bootstrap CSS in your project,
install the bootstrap npm package.

npm install bootstrap // Install the bootstrap package

After installing the bootstrap package add the following line to the src/index.js file inside your
project structure.

// Add the line to use Bootstrap


import 'bootstrap/dist/css/bootstrap.css'

You can add additional styling according to your taste using custom css. Create a new file like
Home_page.css and import it inside your JavaScript file and style your page according to your
need.

body {
background-color :#EBEFF2;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}

https://www.c-sharpcorner.com/ebooks/ 40
.backcard {
height : 500px;
width: 420px;
background-color: #ECF0F2;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
box-shadow: 10px 10px 20px #D3DBE7, -0.5rem -0.5rem 20px white;
border-radius: 20px;
}

.center-align {
width: fit-content;
margin: auto;
}

.top-align{
width: 100%;
position: relative;
}

.button-container{
width: 50%;
margin: 1.5rem auto;
display: flex;
flex-direction: column;
}
.set-button{
border-radius: 1px;
width: 13.5rem !important;
border-radius: 16px;
margin-top: 5% auto;
}
.logo {
margin-top: 5px;
}

.logoImage {
width: 15rem;
}

.start-guide-text {
margin-top: 1.2rem !important;
max-width: 70%;
text-align: center;

https://www.c-sharpcorner.com/ebooks/ 41
.color-logo {
font-weight: bold;
color: #7028FF;
}

.support-logoImage {
width: 1.8rem;
margin: 0px 0.5em 0px 0.5em;
}

.support-logo{
display: flex;
margin-top: 1em;
}

With this, we have created our first page for our project. Run the command npm start to view the
page. But wait, you won’t be able to view the page not yet. To view the page, we need to define
the routes of the page. Install a npm package named react-router-dom

npm install react-router-dom // Install react-router-dom

After installing react-router-dom, modify the index.js file. Your index.js file should look like -

// src/Index.js File
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// use BrowserRouter from react-router-dom
import { BrowserRouter } from 'react-router-dom';
// Add the line to use Bootstrap
import 'bootstrap/dist/css/bootstrap.css'

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);

// If you want to start measuring performance in your app, pass a function


// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

After modifying your index.js for routing service modify your App.js file

https://www.c-sharpcorner.com/ebooks/ 42
// src/App.js
import React from "react";
import HomePage from "./Components/HomePageComponent/Home_page";

import { Route,Routes } from "react-router-dom";

function App() {
return (
<switch>
<Routes>
<Route path = "/" element = {<HomePage />}/>
</Routes>
</switch>

);
}

export default App; With this, you are all set to view your first page. Now run your app and view
the first page.

Create New Account Action Page


Now, let’s move on to the next pages and their functionalities.
In the Home page we are providing two options to a user, that are.

• Create new account.


• Recover Account.

So now we are going to build the Create New Account page.


Follow the steps below:

Step 1: Create a new JavaScript (.js) file in the Components folder, naming Create_account.js.

https://www.c-sharpcorner.com/ebooks/ 43
Step 2: Modify the App.js file where we are defining the routes for our project. Here import your
Create_account.js file and then define a route to it.

//Define Routes
//Import the JavaScript file
import CreateWallet from "./Components/WalletActions/Create_wallet"

//Create the route


<Route path = "/create-wallet" element = {<CreateWallet />}/>

Remember to provide routes for your file.

Step 3: Now in your Create_wallet.js file write your page code, along with functionalities.

//Create_wallet.js
import React, { useEffect, useState } from "react";
import "./CSS/Create_wallet.css"
import logo from '../../Images/yourCryptoLogo-removebg-preview.png';
import Back from '../../Images/87-875958_back-arrow-in-circle-symbol-removebg-
preview.png'
import { useNavigate } from "react-router-dom";

function Create_wallet() {
const [isCopied, setIsCopied] = useState(false);
const [isHidden, setIsHidden] = useState(true);
const [Phrase, setPhrase] = useState('');
const [Privatekey, setPrivatekey] = useState('');
const [Address, setAddress] = useState('');

const navigate = useNavigate();

https://www.c-sharpcorner.com/ebooks/ 44
useEffect(() => {
console.log("here");
// Calling the createAccount endpoint created in the server app
fetch('http://localhost:3000/createAccount')
.then(response => response.json())
.then(data => {
console.log(data);
setPhrase(data.Mnemonic);
setPrivatekey(data.PrivateKey);
setAddress(data.Address);
});
}, [])

const arr = Phrase.split(' ');

function getBack() {
navigate("/")
}

function getNext() {
SaveToLocalStorage();

navigate("/wallet")
}

function SaveToLocalStorage() {
const AccountDetails = [{
AccountName: "Account 0",
Mnemonic: Phrase,
PrivateKey: Privatekey,
Address: Address
}];

let activeNetwork = {
NetworkName: "Polygon-Mumbai",
Network: "Testnet",
RPC_URL: "https://rpc-mumbai.maticvigil.com",
Chain_ID: "80001",
Currency: "MATIC"
}

localStorage.setItem('ActiveNetwork', JSON.stringify(activeNetwork));
localStorage.setItem("ActiveAccount", JSON.stringify(AccountDetails[0]));
}

function copyToClipboard() {
navigator.clipboard.writeText(Phrase)
.then(() => {

https://www.c-sharpcorner.com/ebooks/ 45
setIsCopied(true);

setTimeout(() => {
setIsCopied(false);
}, 3000);
})
.catch(err => {
console.error('Error copying to clipboard:', err);
});
}

const unHide = () => {


setIsHidden(false);
}

return (
<div>
<div id="copy-notification-box" className={`copy-notification-box
${isCopied ? 'slide-in opacity' : 'slide-out '}`}>
<p>Passphrase Copied</p>
</div>

<div className="create-backcard">
<div><button type="button" className="create-backButton"
onClick={getBack} ><img src={Back} alt="back" className="create-backButton"
/></button>
</div>

<div className="logo center-align">


<img src={logo} alt='Wallet' className="logoImage policy-tab" />
</div>

<div className="create-top-align"><h2 className="create-center-


align">Your Secret/Recovery Phrase</h2>
<div className="your-passphrase">
<p>Please write your passphrase on a paper and store it in a safe
place. You can recover your account using this passphase.</p>
<h6> <b>Your passphrase</b></h6>
</div>
<div className={`hide-phrase ${!isHidden ? 'display-none' : ''}`}>
<div className="eye-mark" onClick={unHide}>
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35"
fill="currentColor" class="bi bi-eye eye-color" viewBox="0 0 16 16">
<path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8M1.173
8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168
5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83

https://www.c-sharpcorner.com/ebooks/ 46
1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-
2.457A13.134 13.134 0 0 1 1.172 8z" />
<path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5M4.5 8a3.5 3.5
0 1 1 7 0 3.5 3.5 0 0 1-7 0" />
</svg>
</div>
<div className="text eye-color" onClick={unHide}>Reveal Secret
Recovery Phrase</div>
<p className="eye-color">Please ensue that no one is watching your
screen</p>
</div>
<div className={`wrapper ${isHidden ? 'display-none' : ''}`}>
{arr.map((item, index) => (
<div key={index} className="phrase">{item}</div>
))}
</div>
<div className="down-buttons">
<button type='button' className="btn btn-primary bttn"
onClick={copyToClipboard} disabled={isHidden}>Copy </button><br />
<button type='button' className="btn btn-primary bttn"
onClick={getNext} disabled={isHidden}>Next</button>
</div>
</div>
</div>
</div>
);
}

export default Create_wallet;

Here, I am calling the API endpoint createAccount, that I have created in my server app while
creating the endpoints.

After that storing the account details and showing the passphrase from it on the screen.

If you face any problem while fetching the API response, then you can add the Cors policy to
your server app.

In your server.js app where the endpoints are created, install cors package and include it into
your server project.

npm install cors // Install Cors package

After you have installed the package, add the below two lines in your server.js file and then
restart the server app.

//Include cors
const cors = require('cors');

//Use Cors
app.use(cors());

https://www.c-sharpcorner.com/ebooks/ 47
With this there shouldn't be any problem while fetching the data. Please ensure the endpoint
URl while fetching

Step 4: Design your page accordingly using CSS.

/* Custom CSS for Create_wallet.js


Create_wallet.css */
*{
margin: 0px;
padding: 0;
box-sizing: border-box;
}
body {
background-color :#EBEFF2;
max-width: 100%;
max-height: 100%;
overflow: hidden;

}
.create-backcard {
width: 550px;
background-color: #ECF0F2;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
box-shadow: 10px 10px 20px #D3DBE7, -0.5rem -0.5rem 20px white;
}
.create-backButton {
margin-top: 15px;
border: none;
background: none;
max-height: 60px;
max-width: 60px;
}
.create-center-align {
width: fit-content;
margin: auto;
}
.create-top-align{
width: 100%;
position: relative;
top: 2%;
}
.your-passphrase {
width: 80%;
margin: 20px auto;
}
h6 {

https://www.c-sharpcorner.com/ebooks/ 48
width: fit-content;
margin: auto;
}
p {
width: 90%;
margin: 20px auto;
text-align: center;
justify-content: center;
}
.padding-change {
padding: 0rem 1rem;
}
.border-radius-change {
border-radius: 10px;
}
.down-buttons {
width: 80%;
margin: 45px auto;
display: flex;
flex-direction: row;
}
.bttn {
margin-left: 6rem;
}
.wrapper {
width: 80%;
margin: auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: 50px;
}
.phrase {
background-color: rgba(209, 216, 219, 0.907);
border-radius: 20px;
text-align : center;
color: black;
font-weight: 600;
display: flex !important;
justify-content: center !important;
align-items: center;
}
.logoImage {
width: 10rem;
}
.hide-phrase {
background-color: rgba(25, 23, 23, 0.774);
width: 80%;

https://www.c-sharpcorner.com/ebooks/ 49
height: 14.5rem;
margin: auto;
display: flex;
border-radius: 15px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.display-none {
display: none !important;
}
.eye-color {
color: white ;
cursor: pointer;
}
.copy-notification-box {
background-color: #0d6efd;
color: white;
font-weight: 200%;
width: 20rem;
text-align: center;
float: right;
margin: 20px 20px;
border-radius: 10px;
display: flex;
justify-content: center;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.copy-notification-box.opacity {
opacity: 1;
}
.copy-notification-box.slide-in {
animation: slideIn 0.5s ease-in-out;
}
.copy-notification-box.slide-out {
animation: slideOut 0.5s ease-in-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(100%);
}

to {
opacity: 1;
transform: translateX(0);

https://www.c-sharpcorner.com/ebooks/ 50
}
}
@keyframes slideOut {
from {
opacity: 1;
transform: translateX(0);
}

to {
opacity: 0;
transform: translateX(100%);
}
}

The page is designed, now add the navigation to navigate to your create wallet page.

Step 5: In your Hom_page.js i.e., the first page, add the URL navigation on the button click
event. In other words, add the functionality in your home page that will take your users to the
Create Wallet page whenever the Create Wallet button is clicked.

// Function executed on button click


const openCreate = () => {
navigate("/create-wallet")
}

openCreate function will be executed whenever the Create Wallet button is clicked. The function
call on the click event should be like:

// openCreate function called on click.


<button type='button' className="btn btn-primary set-button center-align"
onClick={openCreate}>Create new account</button><br />

With this, whenever the Create Wallet button is clicked, the user will be redirected to the
Create_wallet page.

Step 6: View your Create Wallet Page.

https://www.c-sharpcorner.com/ebooks/ 51
Create Recover Account Action Page
After we have created our Create Wallet page, it’s now time to create the Recover Wallet
Account page.Follow the steps below to create the recover wallet page.

Step 1: Create a new file inside the Component folder and name it Recover_wallet.js.

Step 2: Create the route for the recover page in a similar manner that you created the route for
the Create wallet page in the App.js file.

//Define Recover wallet Routes


import RecoverWallet from "./Components/WalletActions/Recover_wallet"

<Route path = "/recover-wallet" element = {<RecoverWallet />}/>

Step 3: Write the code in the Recover_wallet.js file.

//Recover_wallet.js
import React, { useState } from "react";
import "./CSS/Create_wallet.css"
import "./CSS/Recover_wallet.css"
import Back from '../../Images/87-875958_back-arrow-in-circle-symbol-removebg-
preview.png'
import logo from '../../Images/yourCryptoLogo-removebg-preview.png';

import { useNavigate } from "react-router-dom";

function Recover_wallet() {

const [formData, setFormData] = useState(Array(12).fill('')); // Initialize


an array with 12 empty strings
const [showRecoverError, setShowRecoverError] = useState(false);
const [showInputBlankError, setShowInputBlankError] = useState(false);

const [isRecovered, setIsRecovered] = useState(false);

const handleChange = (id, value) => {


const updatedFormData = [...formData];
updatedFormData[id - 1] = value;
setFormData(updatedFormData);
}
const navigate = useNavigate();
function getBack() {
navigate("/")
}
function Clear() {
setFormData(Array(12).fill(''))
}
const RecoverAccount = () => {

https://www.c-sharpcorner.com/ebooks/ 52
const isAnyFieldEmpty = formData.some(value => value.trim() === '');
if (isAnyFieldEmpty) {
InputBlankError();
}
const combinedString = formData.join(' ');
{ getAccount(combinedString) }
}
function getAccount(passPhrase) {
console.log(passPhrase)
// Calling the recover endpoint created in the server app
const url = `http://localhost:3000/recover/mnemonic/${passPhrase}`
fetch(url, {
method: 'POST'
}).then(response => response.json())
.then(data => {
if (data.message === "Success") {
accountRecovered(data.Mnemonic, data.PrivateKey,
data.Address);
}
else {
accountRecoverError();
}
});
}

const accountRecovered = (mnemonic, privateKey, address) => {


SaveToLocalStorage(mnemonic, privateKey, address)

setIsRecovered(true);
// Simulate sliding back after 3 seconds
setTimeout(() => {
setIsRecovered(false);
}, 3000);
// Simulate navigating to a new page after 5 seconds
setTimeout(() => {
navigate('/wallet');
}, 4000);
}

const accountRecoverError = () => {


setShowRecoverError(true);
// Simulate sliding back after 3 seconds
const timeoutId = setTimeout(() => {
setShowRecoverError(false);
}, 3000);
// Simulate navigating to a new page after 5 seconds
setTimeout(() => {
Clear();

https://www.c-sharpcorner.com/ebooks/ 53
}, 4000);

}
const InputBlankError = () => {
setShowInputBlankError(true);
// Simulate sliding back after 3 seconds
setTimeout(() => {
setShowInputBlankError(false);
}, 3000);
}
function SaveToLocalStorage(Phrase, Privatekey, Address) {
const AccountDetails = [{
AccountName: "Account 0",
Mnemonic: Phrase,
PrivateKey: Privatekey,
Address: Address
}];
let activeNetwork = {
NetworkName: "Polygon-Mumbai",
Network: "Testnet",
RPC_URL: "https://rpc-mumbai.maticvigil.com",
Chain_ID: "80001",
Currency: "MATIC"
}
localStorage.setItem('ActiveNetwork', JSON.stringify(activeNetwork));
localStorage.setItem("ActiveAccount", JSON.stringify(AccountDetails[0]));
}

return (
<div>
<div id="recover-confirm-notification-box" className={`recover-
confirm-notification-box ${isRecovered ? 'slide-in opacity' : 'slide-out '}`}>
<p>Account Recovered: Passphrase correct</p>
</div>

<div id="recover-error-notification-box" className={`recover-error-


notification-box ${showRecoverError ? 'slide-in opacity' : 'slide-out '}`}>
<p>Failed to Recover Account</p>
</div>

<div id="recover-error-notification-box" className={`recover-error-


notification-box ${showInputBlankError ? 'slide-in opacity' : 'slide-out '}`}>
<p>Please fill all the boxes</p>
</div>

<div className="create-backcard">

https://www.c-sharpcorner.com/ebooks/ 54
<div><button type="button" className="create-backButton"
onClick={getBack} ><img src={Back} alt="back" className="create-backButton"
/></button>
</div>
<div className="logo center-align">
<img src={logo} alt='Wallet' className="logoImage policy-tab"
/>
</div>

<div className="create-top-align"><h2 className="create-center-


align">Recover Your Wallet</h2>
<div className="your-passphrase">

<p>Please provide your passphrase in the sequential order


that you recorded during account creation.</p>
<h6>Your passphrase</h6>
</div>
<div className="wrapper">
{Array.from({ length: 12 }, (_, index) => (
<div key={index}>
<input
type="text"
className="phrase-input"
required
id={index + 1}
value={formData[index]}
onChange={(e) => handleChange(index + 1,
e.target.value)}
/>
</div>
))}
</div>
<div className="recover-down-buttons">
<button type='button' className="btn btn-primary recover-
bttn" onClick={RecoverAccount} >Recover</button><br />
<button type='button' className="btn btn-primary recover-
bttn" onClick={Clear}>Clear</button>
</div>
</div>
</div>
</div>
);
}

export default Recover_wallet;


Here, I am calling the API endpoint recover/mnemonic, that I have created in my
server app while creating the endpoints. This endpoint takes the passphrase from

https://www.c-sharpcorner.com/ebooks/ 55
the user and returns the wallet account with the address and private key which
are later used in the wallet.
Step 4: Design your Recover Wallet page with CSS.
/* Recover_wallet.css */
body {
background-color :#EBEFF2;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
.phrase-input {
width: 100%;
background-color: none;
border: none;
height: 100%;
background-color: rgba(209, 216, 219, 0.907);
border-radius: 20px;
text-align : center;
color: black;
font-weight: 600;
}
.phrase-input:focus {
background-color: white;
}
.recover-down-buttons {
width: 80%;
margin: 45px auto;
display: flex;
flex-direction: row;
justify-content: space-around;
}
.recover-bttn {
width: 5.5rem;
}
.recover-confirm-notification-box {
background-color: rgb(65, 135, 65);
color: white;
font-weight: 200%;
width: 20rem;
text-align: center;
float: right;
margin: 20px 20px;
border-radius: 10px;
display: flex;
justify-content: center;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}

https://www.c-sharpcorner.com/ebooks/ 56
.recover-confirm-notification-box.opacity {
opacity: 1;
}
.recover-confirm-notification-box.slide-in {
animation: slideIn 0.5s ease-in-out;
}
.recover-confirm-notification-box.slide-out {
animation: slideOut 0.5s ease-in-out;
}
.recover-error-notification-box {
background-color: rgb(158, 26, 26);
color: white;
font-weight: 200%;
width: 20rem;
text-align: center;
float:right;
margin: 20px 20px;
border-radius: 10px;
display: flex;
justify-content: center;
position: absolute;
right: 0px;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.recover-error-notification-box.opacity {
opacity: 1;
}
.recover-error-notification-box.slide-in {
animation: slideIn 0.5s ease-in-out;
}
.recover-error-notification-box.slide-out {
animation: slideOut 0.5s ease-in-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(100%);
}

to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slideOut {
from {
opacity: 1;

https://www.c-sharpcorner.com/ebooks/ 57
transform: translateX(0);
}

to {
opacity: 0;
transform: translateX(100%);
}
}

Step 5: Modify the route of the Recover Wallet page in the Home page and then view the page.

// Function executed on button click


const openRecover = () => {
navigate("/recover-wallet")
}

// Add the function call in the Recover Account button


<button type='button' className="btn btn-primary set-button center-align"
onClick={openRecover}>Recover Account</button>

With this, the recover wallet page is ready to be used. View your page.

With this we have created three pages for our wallet.

Summary
In this chapter, we have started with the Wallet design which would support our server-side
programming and provide an interactive and aesthetic user experience to a new user.
In this chapter, we have involved ourselves with the knowledge of creating a new react project
and designing pages using it. We also learned about React-router-Dom using which we have
navigate through the webpages. With all these we have successfully created designs for our
beginning three pages: Home page, create wallet page and recover wallet page.
Now in the next chapter, we will be moving forward with designing the wallet page where we will
be showing the notifications. So, stay with me, and let’s meet again in the next chapter.

https://www.c-sharpcorner.com/ebooks/ 58
8
Designing the User-
Interface (Part 2)

Overview

In this chapter, we elevate our wallet application by integrating real-


time notifications. We commence by constructing the wallet page
using React.js, implementing features like fetching account
balances and transaction data. Through server-side API requests,
we enable dynamic notification retrieval, enhancing user awareness
of transaction activity. CSS styling is applied for improved
aesthetics. Additionally, methods for adding new wallet addresses
to the Alchemy webhook are discussed, concluding our exploration
of wallet development.

https://www.c-sharpcorner.com/ebooks/ 59
Welcome back, Developers! Last time, we made progress by designing the user interface for our
wallet using React.js. We created three essential pages: the Homepage, Create Wallet page,
and Recover Wallet page.
Now, we're moving forward. This chapter focuses on expanding our wallet's capabilities. We'll
work on building a page where users can see notifications in real-time. Also, we'll learn how to
add a new address to the system so we can get notifications effectively.
Let's keep moving and explore the world of real-time blockchain notifications!

Creating Wallet Page


In continuation to our previous chapter, let’s focus on building the wallet page and
understanding its functionalities. To start with the creation of the wallet page, follow the steps
below:

Step 1: Create a new JavaScript (.js) file in the Components folder, naming Wallet.js.

Step 2: Modify the App.js file where we are defining the routes for our project. Here import your
Create_account.js file and then define a route to it. After that modify the navigate routes for your
previous pages, create wallet & recover wallet to redirect to the wallet page.

Step 3: In your Wallet.js file, write down the below code.

// Wallet.js
import React, { useEffect, useState } from "react";
import './CSS/Wallet.css';
import './CSS/loadingSpinner.css'
import copyLogo from '../../Images/copy.png'
import sendLogo from "../../Images/send.png";
import logo from '../../Images/yourCryptoLogo-removebg-preview.png';
import noData from "../../Images/no_token_nft-removebg-preview.png";

function Wallet() {

const [Ammout, setAmount] = useState(null);


// Activity Data of User
const [activityData, setActivityData] = useState([]);
// Copied Message
const [showCopiedMessage, setShowCopiedMessage] = useState(false);
//Sets active animation for token,nft and activity nav tab
const [isTokensActive, setIsTokensActive] = useState(false);
const [isActivityActive, setIsActivityActive] = useState(true);
const [isNFTActive, setIsNFTActive] = useState(false)
// // Sets the active Network details
const [activeNetwork, setActiveNetwork] = useState(
{
NetworkName: '',
}
);
// Sets the active account details
const [activeAccount, setActiveAccount] = useState('');

https://www.c-sharpcorner.com/ebooks/ 60
useEffect(async () => {
let networkName = await RetrieveNetworkFromLocalStorage()
setActiveNetwork(networkName)
let accountName = RetrieveAccountDetailsFromLocalStorage();
setActiveAccount(accountName);

let address = RetrieveAccountFromLocalStorage();


let rpc = RetrieveRPCFromLocalStorage();
// Fetch balance of the account using balance endpoint from server
fetch(`http://localhost:3000/balance?RPC=${rpc}&address=${address}`, {
method: 'POST'
}).then(response => response.json())
.then(data => {
let account_balance = parseFloat(data.balance);
account_balance = account_balance.toFixed(2);
setAmount(account_balance);
});
// Fetch balance of the account using balance endpoint from server
fetch(`http://localhost:3000/webhook/addAddress`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ address: [address] })
}).then(response => response.json())
.then(data => {
});
// Fetch notifications of the account using notifications endpoint from
server
fetch(`http://localhost:3000/notifications/${address}`).then(response =>
{
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
console.log(response);
return response.json();
})
.then(data => {
console.log("this");
console.log(data);
setActivityData(data.result)
});
}, [])

function RetrieveAccountFromLocalStorage() {
const Account = JSON.parse(localStorage.getItem('ActiveAccount'));

if (Account) {

https://www.c-sharpcorner.com/ebooks/ 61
return (
Account.Address
)
}
}
async function RetrieveNetworkFromLocalStorage() {
const Network = JSON.parse(localStorage.getItem('ActiveNetwork'))
if (Network) {
return (
Network
)
}
}
function RetrieveAccountDetailsFromLocalStorage() {
const Account = JSON.parse(localStorage.getItem('ActiveAccount'))

if (Account) {
return (
Account
)
}
}
function RetrieveRPCFromLocalStorage() {
const Network = JSON.parse(localStorage.getItem('ActiveNetwork'))

if (Network) {
return (
Network.RPC_URL
)
}
}
// Copy Function
function onCopy() {
navigator.clipboard.writeText(RetrieveAccountFromLocalStorage())
.then(() => {
setShowCopiedMessage(true);
setTimeout(() => {
setShowCopiedMessage(false);
}, 3000);
})
.catch(err => {
console.error('Error copying to clipboard:', err);
});
}

// Function to handle click events


const handleTokensClick = () => {
setIsActivityActive(false);

https://www.c-sharpcorner.com/ebooks/ 62
setIsNFTActive(false);
setIsTokensActive(true);
};
const handleActivityClick = () => {
setIsActivityActive(true);
setIsNFTActive(false);
setIsTokensActive(false);
};
const handleNFTClick = () => {
setIsActivityActive(false);
setIsNFTActive(true);
setIsTokensActive(false);
};

// HTML Object
return (
<div>
<div id="wallet-notification-box" className={`wallet-notification-box
color-info ${showCopiedMessage ? 'slide-in opacity' : 'slide-out '}`}>
<p>Copied</p>
</div>

<div className="wallet-logo center-align">


<img src={logo} alt='Wallet' className="wallet-logo-width" />
</div>

<div className="wallet-backcard">
<div className="top-section">
<div className="Network">
<div className="dropdown">
<div className="btn network-button dropdown-toggle
custom-dropdown-toggle d-flex" type="button" id="NetworkdropdownMenu" data-bs-
toggle="dropdown" aria-expanded="false">
<div className="logo-importToken d-flex">
<div className={`importToken-logo static-
logo-color`}>{Array.from(activeNetwork.NetworkName)[0]}</div>
<div>{activeNetwork.NetworkName}</div>
</div>
</div>
</div>
</div>
<div className="dropdown">
<div className="btn account-button dropdown-toggle"
type="button" id="AccountdropdownMenu" data-bs-toggle="dropdown" aria-
expanded="false">
{activeAccount.AccountName}
</div>
</div>

https://www.c-sharpcorner.com/ebooks/ 63
<div className="more-menu" >
<svg xmlns="http://www.w3.org/2000/svg" width="18"
height="18" fill="currentColor" class="bi bi-three-dots-vertical" viewBox="0 0 16
16">
<path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3
0m0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3
0" />
</svg>
</div>
</div>

<div className="middle-section">
<div className="Address d-flex">
<div className="number">{activeAccount.Address}</div>
<button type="button" className="copy d-flex"
onClick={onCopy}>...<img src={copyLogo} alt="copy" className="copyImage"
/></button>
</div>
<div className="balance">
<div className="value">{Ammout}</div>
<div className="symbol">{activeNetwork.Currency}</div>
</div>
<div className="Transfer d-flex">
<button type="button" className="Send">Send<img
src={sendLogo} alt="Send" className="send-image" /></button>
</div>
<hr />
<div className="navigation d-flex">
<div className={`Tokens ${isTokensActive ? 'navigation-
active' : ''}`} onClick={handleTokensClick} >Tokens</div>
<div className={`Activity ${isNFTActive ? 'navigation-
active' : ''}`} onClick={handleNFTClick}>NFT</div>
<div className={`Activity ${isActivityActive ?
'navigation-active' : ''}`} onClick={handleActivityClick}>Activity</div>
</div>
<div className="navigation-tab-output">
<div className={`ImportedTokens ${!isTokensActive ?
'display-none' : ''}`}>
<div className={`noData`}>
<div className="noData-image"><img src={noData}
alt='NoData' className="" /></div>
<div className="noData-text">No Imported Token's
to show</div>
<div className="noData-link"><a href="#">Lear
more</a></div>
</div>
<div className="importToken">
<div className="bottomLine-On-hover">

https://www.c-sharpcorner.com/ebooks/ 64
<a href="#" className="import"><svg
xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0
0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4" />
</svg> Import Token</a>
</div>
</div>
<div className="importToken">
<div className="bottomLine-On-hover">
<a href="/wallet" className="import"> <svg
xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1
0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2z" />
<path d="M8 4.466V.534a.25.25 0 0 1 .41-
.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466" />
</svg> Refresh List</a>
</div>
</div>

</div>
<div className={`NFTList ${!isNFTActive ? 'display-none'
: ''}`}>
<div className={`noData`}>
<div className="noData-image"><img src={noData}
alt='NoData' className="" /></div>
<div className="noData-text">No NFT's Yet</div>
<div className="noData-link"><a href="#">Lear
more</a></div>
</div>

<div className="importToken">
<a href="#" className="import"><svg
xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1
0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4" />
</svg> Import NFT</a>
</div>
<div className="importToken">
<a href="#" className="import"> <svg
xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0
4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2z" />
<path d="M8 4.466V.534a.25.25 0 0 1 .41-
.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466" />

https://www.c-sharpcorner.com/ebooks/ 65
</svg> Refresh List</a>
</div>
</div>

<div className={`ActivityList ${!isActivityActive ?


'display-none' : ''}`}>
<div>
{activityData.map((activity, index) => (
<div key={index} className="Activity-Info d-
flex" >
<div className="Activity-
name">{activity.notification_msg}</div>
</div>
))}
</div>
</div>
</div>
</div>

<div className="footer-section">
<div className="footer-support"><a href="" className="support-
link">@support.yourCrypto</a></div>
</div>
</div>
</div>
);
}

export default Wallet;

Here, I am calling two endpoints created in the server app. I am fetching the balance of the
address from /balance endpoint and current notifications from the /notifications endpoint.

Step 4: Now let’s add CSS to our wallet. Adding CSS will enhance the wallet’s user interaction
and layout.

/* Wallet.css */
body {
background-color: #EBEFF2;
height: 100%;
}
.wallet-backcard {
width: 1100px;
background-color: #ECF0F2;
position: fixed;
left: 50%;
top: 37%;
transform: translate(-50%,-30%);
box-shadow: 10px 10px 20px #D3DBE7, -0.5rem -0.5rem 20px white;

https://www.c-sharpcorner.com/ebooks/ 66
}
.wallet-logo {
position: fixed;
left: 50%;
top: 10%;
transform: translate(-45%,-95%);
}
.wallet-logo-width {
width: 10rem;
}
.wallet-center-align {
width: fit-content;
margin: auto;
}
.wallet-top-align{
width: 100%;
position: relative;
top: 2%;
}
.Network {
width: fit-content;
margin: auto
}
.top-section{
display: flex;
margin: 0rem 0px 1rem 0rem;
justify-content: space-between;
background-color: white;
box-shadow: 10px 10px 20px #D3DBE7, -0.5rem -0.5rem 20px white;
padding: 0.8rem 0px;
}
.middle-section {
margin: 2rem 0px;
min-height: calc(100vh - 340px);
}
.top-section div {
margin: 0px 1rem;
}
.network-button {
border-radius: 0px;
background: white;
color: black;
border: 2px solid rgb(7, 101, 133);
border-radius: 1.5rem
}
.account-button {
width: 20rem;
border-radius: 0px;

https://www.c-sharpcorner.com/ebooks/ 67
background: white;
color: black;
position: fixed;
left: 35%;
font-size: 1.1rem;
font-weight: 500;
}

.Address {
width: 10rem;
margin: auto;
justify-content: center;
border: 2px solid rgb(7, 101, 133);
border-radius: 10px;
}
.Address .number {
width: 5rem;
overflow: hidden;
padding: 0.2rem;
font-size: 0.9rem;
}
.copy {
height: fit-content;
border: none;
padding: 0.2rem;
}
.copyImage {
width: 1.5rem;
padding: 0.2rem;
background-color: transparent;
}
.balance {
width: 50%;
margin: 0.5rem auto;
display: flex;
justify-content: center;
}
.balance .value {
font-size: 3.5rem;
align-self: end;
}
.balance .symbol {
align-self: end;
font-size: 1rem;
color: rgb(7, 101, 133);
}
.importToken{
margin-top: 0.5rem;

https://www.c-sharpcorner.com/ebooks/ 68
display: block;
width: fit-content;
}
hr {
width: 60%;
margin: auto !important;
color: rgb(3, 53, 69);
height: 5px !important;
border-radius: 150px;
}
.importToken-logo{
padding: 4px 12px;
width: fit-content !important;
margin: 0px 5px 0px auto !important;
border-radius: 100px;
font-style: inherit;
font-size: 1.1rem;
font-weight: 500;
}
.Activity-Info {
justify-content: space-between;
padding: 5px 15px;
border-bottom: 2px solid rgb(7, 101, 133);
margin: 4px 0px;
cursor: pointer;
}
.ActivityList {
overflow-y:auto;
}
.display-none {
display: none;
}
.next {
width: 30%;
margin-left: 8px;
}
.next-logo-div {
align-self: center;
}
.Send {
width: 7rem;
margin: 0px auto 15px;
border : none;
background-color: rgb(59, 147, 201);
color: white;
padding: 10px 15px;
border-radius: 50px;
font-weight: 500;

https://www.c-sharpcorner.com/ebooks/ 69
}
.send-image {
width: 1.5rem;
margin: 0px 0px 0px 5px;
}
.navigation {
width: 40%;
margin: 10px auto;
justify-content: space-between;
}
.Tokens, .Activity {
width: 35%;
text-align: center;
font-size: 110%;
font-weight: 400;
cursor: pointer;
}
.Tokens:hover, .Activity:hover {
color: rgb(34, 112, 179);
}
.navigation-active{
border-bottom: 2px solid rgb(34, 112, 179);
}
.custom-dropdown-toggle {
display: flex;
align-items: center;
}
.static-logo-color {
background-color: lightblue;
}
.coloumn {
width: 40%;
margin: auto;
}
.text-align-center {
text-align: center;
}
.form-control {
padding: 8px;
margin-top: 10px ;
}
.navigation-tab-output {
width: 60%;
height: 20rem;
margin: 1rem auto;
}
.footer-section {
margin: 2rem;

https://www.c-sharpcorner.com/ebooks/ 70
display: flex;
justify-content: center;
align-items: center;
}
.support-link{
text-decoration: none;
font-family: Verdana, Geneva, Tahoma, sans-serif;
cursor: pointer;
font-weight: 500;
}
.support-link:hover {
border-bottom: 2px solid #6489f7b8;
}
.noData {
width: fit-content;
margin: auto;
}
.noData-image {
width: fit-content;
margin: auto;
}
.noData-text {
color: #aeb1b4;
font-weight: 500;
font-size: 1.1rem;
font-family: cursive;
}
.noData-link {
margin: auto;
font-family: cursive;
width: fit-content;
}
.noData-link a {
text-decoration: none;
}
/* Notification box */
.wallet-notification-box {
background-color: rgb(65, 135, 65);
color: white;
font-weight: 200%;
width: 20rem;
text-align: center;
float: right;
margin: 20px 20px;
border-radius: 10px;
display: flex;
justify-content: center;
opacity: 0;

https://www.c-sharpcorner.com/ebooks/ 71
transition: opacity 0.5s ease-in-out;
position: absolute;
right: 0px;
opacity: 0;
}
.color-info{
background-color: rgb(20, 154, 198);
}
.wallet-notification-box.opacity {
opacity: 1;
}
.wallet-notification-box.slide-in {
animation: slideIn 0.5s ease-in-out;
}
.wallet-notification-box.slide-out {
animation: slideOut 0.5s ease-in-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slideOut {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(100%);
}
}

With this, the designing of the Wallet screen is completed.


You can view the page at the route that you mentioned in the App.js file. In my case it was
“/wallet”

https://www.c-sharpcorner.com/ebooks/ 72
But wait, even though the wallet is created, and we are good to go, but still, won’t be getting any
notification from the Alchemy webhook to our personal server. You ask the reason?
Well, it’s because the new wallet’s address won’t be added to the webhook. If your new wallet’s
address is added, then it is good enough you will receive the updates but if not, you need to add
the wallet address to the webhook. So how do I add a new wallet address? Let’s look.

How to Add New Wallet Address to the Created Alchemy Webhook


If you want the Alchemy webhook to notify you whenever there is a transaction at an address,
you must add that address to the webhook. Remember, the 50,000-address limit for a webhook.
We can add a new address to an existing webhook in two ways.

• Using the dashboard UI


• Using Alchemy API.

Let me show you both the ways one by one.

Using Alchemy Dashboard


Follow the steps given to update the address.

Step 1: Log In to Alchemy dashboard.


Step 2: Visit Webhooks tab in the left navbar.
Step 3: Click on the Address activity webhook that you want to update.
Step 4: Add/Remove addresses according to your need.

https://www.c-sharpcorner.com/ebooks/ 73
Step 5: Click on the Update Webhook button to update the webhook addresses.

Using Alchemy API endpoint


Every time you create a new wallet, you will get a new address and then adding that address
manually through the dashboard is a tedious task. We can automate that task by creating an
API that will be called every time a new address is generated. This custom API will call the
Alchemy API to update the webhook address.
Let’s now create the API that will call the Alchemy API and update the webhook address.
In your server.js file where you handle the server logics, create an endpoint
“/webhook/addAddress”

// Endpoint to check and update the webhook addressess


app.post('/webhook/addAddress', (req, res) => {
const address = req.body.address;
console.log(address)
const query = "SELECT COUNT(WalletAddress) as PresentOrNot FROM
monitoringAddress where WalletAddress = ?"
connection.query(query, [address[0]], async (err, results) => {
if (err) {
console.error('Error fetching notifications from MySQL:', err);
res.status(500).json({ error: 'Internal Server Error' });
return;
}

if (results[0].PresentOrNot == 1) {
res.setHeader('Content-Type', 'application/json');
res.status(200).json({ message: "Address already added for
monitoring" });
}

else if (results[0].PresentOrNot == 0) {
let finalResult = await UpdateWebhookAddress(address)
if(finalResult.statusCode == true){
res.setHeader('Content-Type', 'application/json');

const insertQuery = "INSERT INTO monitoringAddress VALUES (?);"


connection.query(insertQuery,[address[0]], (err,result) => {
if (err) {
console.error('Error Inserting Address to
monitoringAddress from MySQL:', err);
res.status(500).json({ error: 'Internal Server Error' });
return;
}
res.status(200).send(finalResult);
})
}
else if(finalResult.statusCode == false){
res.setHeader('Content-Type', 'application/json');
res.status(500).send(finalResult);

https://www.c-sharpcorner.com/ebooks/ 74
}
}
})
})

async function UpdateWebhookAddress(address) {


try {
const XAclechyToken = process.env.AlchemyWebhookToken; // accessing
the token stored in config.

const requestData = {
webhook_id: process.env.WebhookId,
addresses_to_add: address,
addresses_to_remove: []
};

const response = await


axios.patch("https://dashboard.alchemy.com/api/update-webhook-addresses",
requestData, {
headers: {
"Accept": "application/json",
"X-Alchemy-Token": XAclechyToken,
"Content-Type": "application/json"
}
});

// Check if the request was successful


if (response.status !== 200) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
result = {
statusCode : true,
message: 'Webhook addresses updated successfully!'
}
return result
} catch (error) {
result = {
statusCode: false,
error: error.message
}
console.log(error)
return result;
}
}

Here, I am defining an endpoint which accepts the address which needs to be chacked and
updated in the webhook.
The address needs to be provided in the form of array of strings, i.e., [“user address”].

https://www.c-sharpcorner.com/ebooks/ 75
There is a table created in the database where we are keeping track of all the addresses added
to the webhook. The user address is first checked in the database to confirm it is already added
to the webhook or not. If not, then it is added to the webhook using the alchemy API.
Restart your server without closing your ngrok port to see the changes.
After adding the server-side code. Call the endpoint in your React Wallet file “Wallet.js”

// Wallet.js in React Wallet


// Fetch balance of the account using balance endpoint from server
fetch(`http://localhost:3000/webhook/addAddress`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ address: [address] })
}).then(response => response.json())
.then(data => {
});

Now we are ready to receive and show notifications.


Try getting some faucets into your new wallet account. Click on https://mumbaifaucet.com/ and
paste your wallet address to get some fake Matic in your account.
Refresh your wallet to see the notification.

Summary
In this chapter, we delved into enhancing the functionality of our wallet application by
implementing real-time notifications. We began by creating the wallet page, where users can
view their account details, balances, and transaction activity. The page was designed using
React.js, with various components structured to provide a seamless user experience.
Key steps covered in this chapter include:

• Creating the Wallet Page: We developed the wallet page by defining its layout and
integrating essential functionalities such as fetching account balances and transaction
notifications from the server.
• Implementing Real-Time Notifications: Through API requests to the server, we enabled
the retrieval of real-time notifications for user transactions, enhancing the user's
awareness of account activity.
• Styling the Wallet Interface: CSS styling was applied to the wallet page to improve its
visual appeal and user interaction, ensuring a polished and professional look.

Additionally, we addressed the crucial aspect of adding new wallet addresses to the Alchemy
webhook, allowing users to receive notifications for transactions involving their accounts. Two
methods were discussed: manual addition through the Alchemy dashboard UI and automated
addition via a custom API endpoint.
With the completion of this chapter, the book concludes its exploration of wallet development,
providing developers with the tools and knowledge to enrich their applications with real-time
notification capabilities. By following the steps outlined in this guide, developers can create
robust and user-friendly wallet solutions tailored to their specific needs and requirement

https://www.c-sharpcorner.com/ebooks/ 76
OUR MISSION
Free Education is Our Basic Need! Our mission is to empower millions of developers worldwide by
providing the latest unbiased news, advice, and tools for learning, sharing, and career growth. We’re
passionate about nurturing the next young generation and help them not only to become great
programmers, but also exceptional human beings.

ABOUT US
CSharp Inc, headquartered in Philadelphia, PA, is an online global community of software
developers. C# Corner served 29.4 million visitors in year 2022. We publish the latest news and articles
on cutting-edge software development topics. Developers share their knowledge and connect via
content, forums, and chapters. Thousands of members benefit from our monthly events, webinars,
and conferences. All conferences are managed under Global Tech Conferences, a CSharp
Inc sister company. We also provide tools for career growth such as career advice, resume writing,
training, certifications, books and white-papers, and videos. We also connect developers with their poten-
tial employers via our Job board. Visit C# Corner

MORE BOOKS

You might also like