How to Build a Bitcoin Blockchain Explorer with QuickNode and React

How to Build a Bitcoin Blockchain Explorer with QuickNode and React

In this guide, we will walk through the process of building a Bitcoin blockchain explorer using QuickNode's RPC API and integrating it into a React application. This explorer will allow users to fetch and display block, transaction, and account information from the Bitcoin blockchain.

What is a Blockchain Explorer?

A blockchain explorer is a web application that allows users to browse, search, and visualize activity on a blockchain network. It provides a user-friendly interface to interact with blockchain data, such as viewing blocks, transactions, addresses, and other relevant information. Blockchain explorers are essential tools for developers, researchers, and enthusiasts to monitor and analyze blockchain activity.

What is QuickNode?

QuickNode

QuickNode is a blockchain infrastructure-as-a-service platform that provides developers with fast, reliable access to blockchain nodes through its RPC API services. QuickNode supports multiple blockchain networks, including Bitcoin, Ethereum, Binance Smart Chain, and many others. Developers can leverage QuickNode to build applications that interact with blockchain networks without needing to run their own nodes, offering scalability, robust infrastructure, and comprehensive API endpoints.

Prerequisites

Before getting started, make sure you have the following:

  • Node.js and npm are installed on your machine.

  • Basic understanding of React and JavaScript.

  • Access to a QuickNode account with a Bitcoin RPC API endpoint.

Step 1: Set Up Your QuickNode Solana Endpoint

If you don't already have a QuickNode account, sign up at QuickNode. After creating your account, follow the steps to create a new Bitcoin endpoint.

  1. Access the Dashboard: After logging in, you’ll be directed to the QuickNode dashboard.

  2. Create an Endpoint:

    • Click on the "Create Endpoint" button.

      QuickNode

    • Select "Bitcoin" from the list of supported blockchains.

    • Choose your desired plan (QuickNode offers various plans, including a free tier for testing and development).

      QuickNode

    • Name your endpoint and configure any additional settings as needed.

  3. Deploy the Endpoint: Once configuring your endpoint, click "Create Endpoint." QuickNode will take a few moments to deploy your Bitcoin RPC endpoint.

  4. Copy Endpoint URL: After deployment, you’ll be provided with an endpoint URL. Copy this URL as you’ll need it to connect to the Bitcoin network.

Step 2: Setting Up Your React Application

  1. Create a New React App:

    If you haven't already set up your React project, use create-react-app to create a new project:

     npx create-react-app bitcoin-explorer
     cd bitcoin-explorer
    
  2. Install Dependencies:

    Install Axios for making HTTP requests:

     npm install axios
    

    Axios will be used for handling API requests to QuickNode's RPC API.

  3. Set Up Environment Variables:

    Create a .env file in the root directory of your project and add your QuickNode API endpoint:

     REACT_APP_QUICKNODE_API_URL=https://[your-node-name].[network].quiknode.pro
    

    Replace [your-node-name] and [network] with your actual QuickNode API endpoint details.

Step 3: Implementing BitcoinService for API Calls

Create a BitcoinService.js file in your src directory to handle API requests:

// src/BitcoinService.js
const apiUrl = process.env.REACT_APP_QUICKNODE_API_URL;

export const getBlockInfo = async (blockHash) => {
    try {
        const requestOptions = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                method: 'getblock',
                params: [blockHash],
            }),
        };
        const response = await fetch(apiUrl, requestOptions);
        const data = await response.json();
        return data.result;
    } catch (error) {
        console.error('Error fetching block info:', error);
        throw error;
    }
};

export const getTransactionInfo = async (txid) => {
    try {
        const requestOptions = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                method: 'getrawtransaction',
                params: [txid, true],
            }),
        };
        const response = await fetch(apiUrl, requestOptions);
        const data = await response.json();
        return data.result;
    } catch (error) {
        console.error('Error fetching transaction info:', error);
        throw error;
    }
};

export const getAccountInfo = async (address) => {
    try {
        const requestOptions = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                method: 'validateaddress',
                params: [address],
            }),
        };
        const response = await fetch(apiUrl, requestOptions);
        const data = await response.json();
        return data.result;
    } catch (error) {
        console.error('Error fetching account info:', error);
        throw error;
    }
};

Step 4: Creating React Components

Create React components to interact with the BitcoinService functions:

BlockInfo.js

// src/BlockInfo.js
import React, { useState } from 'react';
import { getBlockInfo } from './BitcoinService';
import './styles.css'; // Import styles.css for styling

const BlockInfo = () => {
    const [blockHash, setBlockHash] = useState('');
    const [blockInfo, setBlockInfo] = useState(null);

    const fetchBlockInfo = async () => {
        try {
            const info = await getBlockInfo(blockHash);
            setBlockInfo(info);
        } catch (error) {
            console.error('Error fetching block info:', error);
        }
    };

    return (
        <div className="container">
            <div className="input-container">
                <input
                    type="text"
                    value={blockHash}
                    onChange={(e) => setBlockHash(e.target.value)}
                    placeholder="Enter Block Hash"
                />
                <button onClick={fetchBlockInfo}>Fetch Block Info</button>
            </div>
            {blockInfo && (
                <div className="result-container">
                    <h2>Block Information</h2>
                    <pre>{JSON.stringify(blockInfo, null, 2)}</pre>
                </div>
            )}
        </div>
    );
};

export default BlockInfo;

TransactionInfo.js

// src/TransactionInfo.js
import React, { useState } from 'react';
import { getTransactionInfo } from './BitcoinService';
import './styles.css'; // Import styles.css for styling

const TransactionInfo = () => {
    const [txid, setTxid] = useState('');
    const [transactionInfo, setTransactionInfo] = useState(null);

    const fetchTransactionInfo = async () => {
        try {
            const info = await getTransactionInfo(txid);
            setTransactionInfo(info);
        } catch (error) {
            console.error('Error fetching transaction info:', error);
        }
    };

    return (
        <div className="container">
            <div className="input-container">
                <input
                    type="text"
                    value={txid}
                    onChange={(e) => setTxid(e.target.value)}
                    placeholder="Enter Transaction ID"
                />
                <button onClick={fetchTransactionInfo}>Fetch Transaction Info</button>
            </div>
            {transactionInfo && (
                <div className="result-container">
                    <h2>Transaction Information</h2>
                    <pre>{JSON.stringify(transactionInfo, null, 2)}</pre>
                </div>
            )}
        </div>
    );
};

export default TransactionInfo;

AccountInfo.js

// src/AccountInfo.js
import React, { useState } from 'react';
import { getAccountInfo } from './BitcoinService';
import './styles.css'; // Import styles.css for styling

const AccountInfo = () => {
    const [address, setAddress] = useState('');
    const [accountInfo, setAccountInfo] = useState(null);

    const fetchAccountInfo = async () => {
        try {
            const info = await getAccountInfo(address);
            setAccountInfo(info);
        } catch (error) {
            console.error('Error fetching account info:', error);
        }
    };

    return (
        <div className="container">
            <div className="input-container">
                <input
                    type="text"
                    value={address}
                    onChange={(e) => setAddress(e.target.value)}
                    placeholder="Enter Account Address"
                />
                <button onClick={fetchAccountInfo}>Fetch Account Info</button>
            </div>
            {accountInfo && (
                <div className="result-container">
                    <h2>Account Information</h2>
                    <pre>{JSON.stringify(accountInfo, null, 2)}</pre>
                </div>
            )}
        </div>
    );
};

export default AccountInfo;

Step 5: Styling and UI Enhancements

CSS Styling (App.css)

/* src/App.css */
.App {
  text-align: center;
  margin-top: 20px;
}

input, button {
  margin: 10px;
  padding: 8px;
  font-size: 16px;
}

pre {
  background-color: #f0f0f0;
  padding: 10px;
  border-radius: 5px;
  overflow-x: auto;
}
/* General styles */
body {
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    margin: 0;
    padding: 0;
}

.container {
    max-width: 800px;
    margin: 20px auto;
    background-color: #fff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.input-container {
    margin-bottom: 20px;
}

.input-container input[type="text"] {
    width: 100%;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
}

.input-container button {
    padding: 10px 20px;
    font-size: 16px;
    background-color: #007bff;
    color: #fff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.input-container button:hover {
    background-color: #0056b3;
}

.result-container {
    margin-top: 20px;
    border: 1px solid #ccc;
    padding: 10px;
    border-radius: 4px;
}

.result-container h2 {
    font-size: 20px;
    margin-bottom: 10px;
}

.result-container pre {
    white-space: pre-wrap;
    word-wrap: break-word;
}

/* Media query for responsiveness */
@media (max-width: 600px) {
    .container {
        padding: 10px;
    }
    .input-container input[type="text"] {
        font-size: 14px;
    }
    .input-container button {
        font-size: 14px;
        padding: 8px 16px;
    }
}

Step 6: Deploying Your Application

Deploy your Bitcoin blockchain explorer application to a hosting service like Vercel, Netlify, or GitHub Pages to make it accessible online and share it with others.

Access the Complete Code and Live Demo

You can access the complete code for this Bitcoin blockchain explorer project on GitHub. Feel free to explore, fork, and contribute to the repository:

GitHub Repository

Additionally, you can check out the live demo of the project to see it in action:

Live Demo

These resources will help you better understand the implementation details and see the project in a fully functional state. Enjoy building with QuickNode and exploring the Bitcoin blockchain!

Running Your Application

To run your Bitcoin blockchain explorer locally:

npm start

Open localhost:3000 to view it in the browser.

Output

Below are the components you've built for your Bitcoin blockchain explorer:

Block Information

Displays information about a specific block on the Bitcoin blockchain.

Transaction Information

Fetches details about a transaction using its transaction ID (txid).

Account Information

Retrieves information related to a Bitcoin account address.

Conclusion

Congratulations! You've successfully built a Bitcoin blockchain explorer using QuickNode's RPC API and React. This project provides a solid foundation for exploring and visualizing blockchain data. You can further enhance it with features such as pagination, real-time updates, and more sophisticated data visualization based on your application's requirements.

I'd love to connect with you on Twitter | LinkedIn | Instagram.

Additional Resources

About QuickNode

QuickNode is dedicated to constructing the infrastructure necessary to uphold the forthcoming era of Web3. Since 2017, we've collaborated with numerous developers and organizations, facilitating the expansion of decentralized applications (dApps) and offering superior access to over 29 blockchains. Sign up for our newsletter to access further content similar to this and remain up-to-date with the latest developments in Web3!