How to build an Ethereum Block-Explorer?
If you are new to web3 and start with your first project, give this a read.
Introduction
I started my journey to become a web3 developer and I stumbled upon this course by Alchemy University. So far this a great course, I've been learning new things daily by doing each and everything myself and creating weekly projects.
Block explorer is such a project which am going to discuss in this post. This project took me quite some time to build because of my little knowledge of ReactJS. I just knew javascript and that's all. If you wanna get started with this project, basic knowledge of React will be sufficient. I'm writing this blog to hone my skills and to help people like me who know little about React. Let's get started๐
Github project link.
Live website link.
What is this project?
In this project, we get data from the Ethereum blockchain and display it on our front end, much like etherscan. You can start by cloning this repository, which provides the base code of the block-explorer project.
Let's first list what our project will contain.
This project will consist of 4 pages: Home, address, transaction hash, and block number.
The home page will have all the information related to transactions, blocks, and addresses. The address page will have more information about the addresses. Similar for transaction hash and block number.
What will you need to get started?
Basic knowledge of ReactJs and React-routers.
For designing Chakra UI (You can use other libraries or frameworks like bootstrap, tailwind css).
Basic of EtherJs and javascript.
Structure of the project
I'm creating this project using React, Alchemy-SDK, and Chakra UI. React for the structure and functionality, Alchemy-SDK for web3 functionality(like to get information from blockchain), and Chakra for designing.
I created different js files for different pages. So I have a home, address, block number, and transaction hash, in total 4 pages. You need react-router to switch between these pages.
Here is my code for routing different pages
<Routes>
<Route path="/" element={<Home />} />
<Route path="/address/:id" element={<Address />} />
<Route path="/block/:id" element={<Block />} />
<Route path="/transactionHash/:id" element={<TransactionHash />} />
</Routes>
Creating a home page.
Let's start to build the home page aka home.js. There are two things that we require to build the home page: Logic and frontend.
Let's start with the logic, here we need to get address, transaction hash and block number from the blockchain using Alchemy-SDK. To build this logic you need basic knowledge of etherjs the methods etherjs or Alchemy-SDK have to read the information on the blockchain, you will also need to know the useState
and useEffect
hooks from react. Here is the logic I've used:
const [blockNumber, setBlockNumber] = useState();
const [recentBlocks, setRecentBlocks] = useState();
const [recentTransactions, setRecentTransaction] = useState();
useEffect(() => {
const blockArray = [];
const transactionArray = [];
const getRecentBlocks = async () => {
const blockNumber = await alchemy.core.getBlockNumber();
setBlockNumber(blockNumber);
for (let i = blockNumber; i >= blockNumber - 20; i--) {
const block = await alchemy.core.getBlock(i);
blockArray.push(block);
}
setRecentBlocks(blockArray);
console.log("recentBlocks", recentBlocks);
};
const getRecentTransactions = async () => {
const { transactions } = await alchemy.core.getBlockWithTransactions(
blockNumber
);
for (let i = 0; i <= 10; i++) {
transactionArray.push(transactions[i]);
}
setRecentTransaction(transactionArray);
console.log("recentTransaction", recentTransactions);
};
getRecentBlocks();
getRecentTransactions();
}, []);
In my actual code, I've used 2 tables for displaying different information, but for simplicity, I've only given one table above. To see the actual code go to the github link provided in the Introduction section.
Now let's talk about the frontend. I'm using Chakra UI for designing purposes, you can use just CSS or any other framework if you want. In our frontend we want a table-like structure so we can store the block number, transaction receipt, and the amount of eth transferred in a block at the same place. Here is the table I've created using Chakra UI.
<TableContainer
overflowY="auto"
maxHeight="630px"
borderBottom={"2px solid white"}
>
<Table
variant="simple"
size="lg"
bg={"black"}
borderBottomEndRadius={"20px"}
>
<TableCaption
placement="top"
fontSize={"20px"}
fontWeight={"bold"}
bg={"black"}
borderTopRadius={"20px"}
color={"whiteAlpha.900"}
>
Latest Blocks
</TableCaption>
<Tbody>
{recentBlocks.map((block, i) => {
return (
<Tr key={i}>
<Td>
Block{" "}
<Text
as="u"
color={"teal.100"}
_hover={{
color: "teal.200",
}}
>
<Link to={`/block/${block.number}`}>
{block.number}
</Link>
</Text>
</Td>
<Td>
Fee recipient{" "}
<Text
as="u"
color={"teal.100"}
_hover={{ color: "teal.200" }}
>
<Link to={`/address/${block.miner}`}>
{block.miner.slice(0, 16)}...
</Link>
</Text>
</Td>
<Td>
<Badge> {block.transactions.length} Txs</Badge>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</TableContainer>
Error Time
The thing is it takes time to fetch information from the Ethereum blockchain. So as soon as you render this table in your react app it's going to throw multiple errors because the information you are trying to display is not available yet. For instance block.number
, block.miner.slice(0, 16)
or block.transactions.length
in the above code. In all of these instances, the block is not defined yet so it's going to throw an error. So now what to do?
Solution
It will be wise to wait till we get all the information required from the blockchain before we render our tables. While we are waiting we cannot provide an empty screen for the users, now can we? So instead put a progress bar or circular progress. If all you know is CSS then it might seem a little tough to apply, but if you use bootstrap or tailwind or chakra UI, it's a piece of cake. Let's see how to implement it.
<CircularProgress isIndeterminate color="green.300" size={"55px"} />
<Text fontSize={"17px"}>Fetching data from Ethereum...</Text>
Just 1 line of code is required and you are all set using chakra UI. But there is still a problem, we have to render it in such a way that either the circular progress is shown (when the data is not ready) or the table (when the data is ready). There is a simple solution, check it out:
return (
<Box backgroundColor={"gray.900"} color={"white"} h={window.innerHeight}>
// Here is the logic we wanted
{!recentBlocks || !recentTransactions ? (
<CircularProgress isIndeterminate color="green.300" size={"55px"} />
<Text fontSize={"17px"}>Fetching data from Ethereum...</Text>
) : (
// rest of your code (tables and other things)
)}
</Box>
);
Here recentBlocks
and recentTransactions
are the arrays where information from the blockchain is stored. If any of them is not defined we will show the circular progress, when both of them are defined we will render our remaining code like tables.
Now you are all set to build your own block explorer!
Other pages
If you are successful in creating the home page, there's nothing else new here. It's the same logic and the same frontend just different values. For eg. on the home page we required block
, transaction
, etc. In the address page, all we require is the address
and the balance
of that address.
You need one more thing to build other pages: const { id } = useParams();
this is part of react-router. We can extract the value in the URL with useParams(). Give it a read or watch a video and you are good to go!
If you find this blog helpful, let me know in the comments or you can reach me on my Twitter.