Building a Blockchain-Based Blog dApp with Hardhat: A Step-by-Step Guide
Nick L.
Posted on August 15, 2024
Blockchain technology is revolutionizing many industries, and blogging is no exception. Imagine a decentralized blogging platform where content creators can post articles, receive votes, and even earn tips directly from their readers, all powered by blockchain. This is the power of decentralized applications (dApps).
In this guide, we’ll walk through the process of developing a decentralized blog application using Hardhat, a popular Ethereum development environment. By the end of this tutorial, you’ll have a basic dApp where bloggers can post content, users can vote on their favorite posts, and readers can tip bloggers directly in cryptocurrency.
Prerequisites
Before we begin, make sure you have the following installed on your machine:
- Node.js (v12.x or later)
- npm (Node Package Manager)
- Metamask extension installed in your web browser
- Basic knowledge of JavaScript, Solidity, and Ethereum concepts
Step 1: Setting Up the Hardhat Project
First, create a new directory for your project and navigate into it:
mkdir blockchain-blog
cd blockchain-blog
Initialize a new Node.js project:
npm init -y
Install Hardhat:
npm install --save-dev hardhat
Set up a new Hardhat project:
npx hardhat
Select “Create a basic sample project” when prompted. This will generate a basic Hardhat project structure with some sample files.
Step 2: Writing the Smart Contract
Our decentralized blog dApp will have a smart contract that handles the core functionalities: posting articles, voting on posts, and tipping bloggers.
Create a new contract file called Blog.sol
in the contracts
directory:
touch contracts/Blog.sol
Open Blog.sol
and add the following Solidity code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Blog {
struct Post {
uint256 id;
string content;
address payable author;
uint256 votes;
uint256 tips;
}
uint256 public postCount = 0;
mapping(uint256 => Post) public posts;
event PostCreated(uint256 id, string content, address payable author);
event PostVoted(uint256 id, uint256 votes);
event PostTipped(uint256 id, uint256 tips);
function createPost(string memory _content) public {
postCount++;
posts[postCount] = Post(postCount, _content, payable(msg.sender), 0, 0);
emit PostCreated(postCount, _content, payable(msg.sender));
}
function votePost(uint256 _id) public {
require(_id > 0 && _id <= postCount, "Invalid post ID");
Post storage post = posts[_id];
post.votes++;
emit PostVoted(_id, post.votes);
}
function tipPost(uint256 _id) public payable {
require(_id > 0 && _id <= postCount, "Invalid post ID");
Post storage post = posts[_id];
post.tips += msg.value;
post.author.transfer(msg.value);
emit PostTipped(_id, post.tips);
}
}
Breakdown of the Smart Contract
-
Post Structure: We define a
Post
structure containing fields likeid
,content
,author
,votes
, andtips
. -
Create Post: The
createPost
function allows bloggers to create new posts. -
Vote Post: The
votePost
function lets users vote for their favorite posts. -
Tip Post: The
tipPost
function allows readers to send ETH directly to the post's author.
Step 3: Compiling the Smart Contract
To compile your smart contract, run the following command:
npx hardhat compile
This command will compile your smart contract and generate the necessary artifacts in the artifacts
directory.
Step 4: Writing the Deployment Script
We need to deploy our smart contract to a blockchain network. Create a new deployment script in the scripts
directory called deploy.js
:
touch scripts/deploy.js
Open deploy.js
and add the following deployment script:
const hre = require("hardhat");
async function main() {
const [deployer] = await hre.ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
const Blog = await hre.ethers.getContractFactory("Blog");
const blog = await Blog.deploy();
await blog.deployed();
console.log("Blog contract deployed to:", blog.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
This script deploys the Blog
contract and logs the contract's address after successful deployment.
Step 5: Deploying the Contract Locally
To deploy the contract on a local Ethereum network, first, start the Hardhat node:
npx hardhat node
In a separate terminal, run the deployment script:
npx hardhat run scripts/deploy.js --network localhost
This deploys the Blog
contract on your local blockchain. You’ll see the deployment address in the terminal output.
Step 6: Building the Front-End
Now that we have our smart contract deployed, we’ll build a simple front-end to interact with it.
Step 6.1: Setting Up React
Set up a React app using Create React App:
npx create-react-app blog-frontend
cd blog-frontend
npm install ethers
Step 6.2: Connecting to the Smart Contract
Create a new file called App.js
in the src
directory and add the following code:
import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import BlogABI from "./BlogABI.json";
const contractAddress = "your_contract_address_here";
function App() {
const [posts, setPosts] = useState([]);
const [content, setContent] = useState("");
useEffect(() => {
const loadPosts = async () => {
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send("eth_requestAccounts", []);
const signer = provider.getSigner();
const blogContract = new ethers.Contract(contractAddress, BlogABI, signer);
const postCount = await blogContract.postCount();
let postsArray = [];
for (let i = 1; i <= postCount; i++) {
const post = await blogContract.posts(i);
postsArray.push(post);
}
setPosts(postsArray);
}
};
loadPosts();
}, []);
const createPost = async () => {
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const blogContract = new ethers.Contract(contractAddress, BlogABI, signer);
const transaction = await blogContract.createPost(content);
await transaction.wait();
setContent("");
window.location.reload();
}
};
const votePost = async (id) => {
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const blogContract = new ethers.Contract(contractAddress, BlogABI, signer);
const transaction = await blogContract.votePost(id);
await transaction.wait();
window.location.reload();
}
};
const tipPost = async (id) => {
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const blogContract = new ethers.Contract(contractAddress, BlogABI, signer);
const transaction = await blogContract.tipPost(id, { value: ethers.utils.parseEther("0.1") });
await transaction.wait();
window.location.reload();
}
};
return (
<div>
<h1>Blockchain Blog</h1>
<input
type="text"
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="Write your post"
/>
<button onClick={createPost}>Post</button>
<div>
{posts.map((post, index) => (
<div key={index}>
<p>{post.content}</p>
<p>Author: {post.author}</p>
<p>Votes: {post.votes}</p>
<p>Tips: {ethers.utils.formatEther(post.tips)} ETH</p>
<button onClick={() => votePost(post.id)}>Vote</button>
<button onClick={() => tipPost(post.id)}>Tip</button>
</div>
))}
</div>
</div>
);
}
export default App;
Step 6.3: Understanding the Front-End
-
Fetching Posts: The
loadPosts
function fetches all posts from the blockchain and stores them in the state. -
Creating a Post: The
createPost
function sends a transaction to create a new post on the blockchain. -
Voting for a Post: The
votePost
function allows users to vote for a specific post. -
Tipping a Post: The
tipPost
function allows users to send ETH to the post’s author as a tip.
Step 6.4: Running the Front-End
Now
, let's run the front-end to interact with our deployed smart contract.
First, make sure you are in the blog-frontend
directory and run:
npm start
This command will start the React development server and open the application in your default web browser. You should now see a simple interface where you can create blog posts, vote on them, and tip the authors.
Conclusion
Congratulations! You’ve built a decentralized blog application that leverages blockchain technology for posting content, voting, and tipping bloggers. This guide covered the entire process from setting up your environment with Hardhat, writing and deploying smart contracts, to building a front-end interface using React.
While this is a basic implementation, it lays the foundation for more advanced features like user authentication, content moderation, and decentralized storage for blog content. As you continue to explore blockchain development, consider experimenting with other Ethereum tools and expanding the functionality of your dApp.
Blockchain is a rapidly evolving field with endless possibilities. By mastering tools like Hardhat and integrating smart contracts with user-friendly interfaces, you’re well on your way to creating innovative and decentralized applications that could shape the future of the web. Happy coding!
Posted on August 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.