Build an NFT Marketplace from Scratch
Create a fully functional NFT marketplace with minting, trading, and royalties.
Introduction
Non-Fungible Tokens (NFTs) have revolutionized digital ownership. An NFT marketplace allows users to mint (create), buy, and sell these unique assets.
In this tutorial, we'll build a marketplace where users can list ERC-721 tokens for sale.
Tech Stack
- Smart Contracts: Solidity, Hardhat
- Frontend: Next.js, Tailwind CSS
- Storage: IPFS (Pinata)
- Blockchain Interaction: Ethers.js
The Smart Contract
We need a contract that holds the NFTs being sold and handles the transfer of funds.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract NFTMarketplace is ReentrancyGuard {
using Counters for Counters.Counter;
Counters.Counter private _itemIds;
Counters.Counter private _itemsSold;
struct MarketItem {
uint itemId;
address nftContract;
uint256 tokenId;
address payable seller;
address payable owner;
uint256 price;
bool sold;
}
mapping(uint256 => MarketItem) private idToMarketItem;
function createMarketItem(
address nftContract,
uint256 tokenId,
uint256 price
) public payable nonReentrant {
require(price > 0, "Price must be at least 1 wei");
_itemIds.increment();
uint256 itemId = _itemIds.current();
idToMarketItem[itemId] = MarketItem(
itemId,
nftContract,
tokenId,
payable(msg.sender),
payable(address(0)),
price,
false
);
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
}
// ... createMarketSale function ...
}
Frontend Integration
We'll use Next.js to build the UI.
- Connect Wallet: Use
window.ethereumto connect Metamask. - Fetch Items: Query the smart contract for unsold items.
- Display: Render the NFTs using their metadata (image from IPFS).
async function loadNFTs() {
const provider = new ethers.providers.JsonRpcProvider();
const contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, provider);
const data = await contract.fetchMarketItems();
const items = await Promise.all(data.map(async i => {
const tokenUri = await contract.tokenURI(i.tokenId);
const meta = await axios.get(tokenUri);
let price = ethers.utils.formatUnits(i.price.toString(), 'ether');
let item = {
price,
tokenId: i.tokenId.toNumber(),
seller: i.seller,
owner: i.owner,
image: meta.data.image,
name: meta.data.name,
description: meta.data.description,
}
return item;
}))
setNfts(items);
}
Conclusion
Building an NFT marketplace involves coordinating on-chain logic with off-chain storage (IPFS) and a responsive frontend. This project is a great portfolio piece for aspiring Web3 developers.