Building a Simple Marketplace DApp on Linea
Learn how to build a decentralized marketplace DApp on Linea using zkEVM, smart contracts, Next.js, and Shadcn UI.
Introduction
In web3 ecosystem, dectralized applications (DApps) has become quite popular because of the ability to provide secure, transparent and trustless service. One of the most popular types of DApps are decentralized marketplaces to give the users ability to buy and sell items directly on the blockchain while removing the need of any middlemen.
In this tutorial, we will build a simple marketplace DApp on Linea, a layer 2 zkEVM technology which provides a scalable and cost-efficient environment while having the security of Ethereum.
We will cover both the frontend and smart contract development.
What is Linea L2 and zkEVM?
Before we start building, let’s take a moment to understand what Linea L2 is and how it utilizes zkEVM to scale effectively.
A zkEVM (zero-knowledge Ethereum Virtual Machine) is a type of Ethereum Virtual Machine which includes zero-knowledge proof technology. Smart contracts can take the advantage of privacy and scalability benefits that comes with zero-knowledge proofs. While the execution of smart contracts, this zero-knowledge proof can be verified quickly and efficiently by other nodes, without the need to re-execute the smart contract.
Linea is a type 2 zkEVM, which means it was designed to be almost fully compatiable with Ethereum Virtual Machine. Developers has the advantage of moving their existing Ethereum applications to Linea without creating any major changes in their code.
In Linea zkEVM transactions are carried out in it’s own network where it creates cryptographic proofs using SNARKs. A SNARK (Succinct Non-interactive Argument of Knowledge) is a type of zero-knowledge proof that allows one party (the prover) to demonstrate to another party (the verifier) that a statement is true. Snarks are known for it’s succinctness which means that the proof is very short and can be quickly verified even with the complex statement being proven. This is why SNARKS are perfect for scenarios where scalability and efficiency are important.
The generated proofs are sent to the Ethereum network for quick and low-cost verification without re-executing all transactions. This maintains compatibility with Ethereum and reduces the cost and time needed for processing transactions, improving scalability and efficiency.
Developers can use Linea to create DApps that are more efficient and cost-effective. These DApps can reach a wider audience because they are easier to use and have lower transaction costs. In the next sections, we'll show you how to build a simple marketplace DApp on Linea.
Understanding the Marketplace DApp Architecture
We will be diving into the architecture of the marketplace DApp and its components.
The marketplace will incorporate smart contracts, frontend, and blockchain integration. The smart contract will include features such as listing items, buying items, and transferring ownership of an item.
The frontend serves as the user interface where buyers and sellers can interact with each other using the smart contract. While having a frontend and backend is important, the way the DApp interacts with the Linea blockchain is also crucial. We will be using the Metamask SDK along with Wagmi and Infura RPC providers.
Setting Up the Environment
We will start by initializing a monorepo, A monorepo (short for monolithic repository) is a software development strategy where code for multiple projects is stored in a single version control repository.
Let’s create a monorepo with pnpm:
Create a new directory for your monorepo and initialize it:
mkdir web3-marketplace-linea
cd web3-marketplace-linea
pnpm init
Create a pnpm-workspace.yaml
file in the root to define your workspace structure:
Here’s what our workspace file structure will be like:
packages
├── site # Frontend built with Next.js, Tailwind CSS, and Shadcn UI
└── blockchain # Smart contracts using Hardhat
Let’s head over to the blockchain
directory and initialize a hardhat project.
cd blockchain
npx hardhat init
You'll be presented with several options:
? What do you want to do? …
❯ Create a JavaScript project
Create a TypeScript project
Create a TypeScript project (with Viem)
Create an empty hardhat.config.js
Quit
For this tutorial we’ll be using TypeScript
project. Hardhat will automatically install the necessary dependencies for you.
Project Structure
After initialization, you'll have a project structure that includes:
contracts/
: Solidity contractsignition/
: Ignition deployment modulestest/
: Test fileshardhat.config.js
: Hardhat configuration
Write the Smart Contract:
Let’s start writing the smart contract:
This contract provides a basic framework for a decentralized marketplace where users can list items for sale, purchase items, and transfer ownership of items. It maintains a record of item ownership and ensures that only valid transactions can occur. Let’s explore the concept of the smart contract a bit more:
- Seller:
- Listing an Item:
- Sellers can list items for sale by calling the
listItem
function. - This function requires a name and price for the item.
- The item is added to the marketplace with a unique ID, and the seller is recorded as the owner.
- Sellers can list items for sale by calling the
- Listing an Item:
- Buyer:
- Purchasing an Item:
- Buyers can purchase items using the
purchaseItem
function. - The function checks that the item exists, the price is correct, and that the item is not already sold.
- The payment is transferred to the seller, and ownership of the item is updated.
- Buyers can purchase items using the
- Purchasing an Item:
- Transferring Ownership:
- Ownership Transfer:
- The
_transferOwnership
function handles the internal logic for transferring item ownership. - It updates the owner in the
items
mapping and adjusts theownedItems
lists for both the previous and new owners.
- The
- Manual Transfer:
- The
transferItem
function allows current owners to transfer their items to another address. - It ensures the sender is the current owner before calling the
_transferOwnership
function.
- The
- Ownership Transfer:
- Retrieving Owned Items:
- Get Items by Owner:
- The
getItemsByOwner
function returns a list of item IDs owned by a specific address.
- The
- Get Items by Owner:
This smart contract facilitates a decentralized marketplace where items can be listed, purchased, and transferred securely, with all transactions and ownership changes recorded on the blockchain.
On the ignition
folder Let’s create Marketplace.ts
to deploy our contract and add the following code:
To compile the contract run the following command:
npx hardhat compile
.env Variables
Before deploying the smart contract, make sure to update the .env
file in the packages/blockchain
directory with the following values:
Deploy the Smart Contract
To deploy the smart contract to the Linea testnet, run the following command:
This will deploy the marketplace smart contract on Linea Sepolia. You can always write a script to deploy quicker by writing small commands like this on package.json
file:
After the deployment we’ll get the contract address
, let’s keep that. We will need it soon while integrating with the frontend.
Frontend: Next.js with Shadcn UI
Create and Navigate to the Project Directory
Initialize Next.js Project
When prompted, choose the following options:
- TypeScript: Yes
- ESLint: Yes
- Tailwind CSS: Yes
src/
directory: No (or Yes, if you prefer)- App Router: Yes
- Import alias: Yes (default @/*)
Install Shadcn UI CLI
Install the necessary UI components like button, card and input as needed.
We will create a wagmi.config.ts
and add the following code:
We will be using wagmi and metamask sdk to connect our wallet and make transactions. Now all that is left is to create a ConnectWallet.tsx
UI component.
On the site/src
directory let’s create a file called constants.ts
and add the following:
Remember the deployed contract that we’ve saved earlier, we’ll add it here. Head over to blockchain/ignition
module and find the artifacts
folder to find the ABI.
Let’s break down the code app.tsx
and explain its key aspects in more detail:
React and Hooks Usage
- The component uses React's
useState
for local state management anduseEffect
for side effects. - It also uses custom hooks from
wagmi
(useAccount
anduseWalletClient
) for blockchain wallet integration.
State Management
- Multiple state variables are defined to manage the component's data.
items
andownedItems
are arrays to store marketplace items.newItemName
andnewItemPrice
are for form inputs when listing a new item.
useEffect for Data Loading
- This effect runs once when the component mounts.
- It calls
loadItems()
andloadOwnedItems()
to populate the state with data from the blockchain.
Smart Contract Interaction
- This function reads data from the smart contract using
client.readContract
. - It first gets the total item count, then fetches details for each item.
Writing to the Blockchain
- This function writes data to the blockchain (listing a new item).
- It first simulates the contract call, then uses
walletClient.writeContract
to execute the transaction.
UI Components and Styling
- The component uses custom UI components like
Card
andButton
. - Tailwind CSS classes are used for styling (
className
props). - Conditional rendering is used to show/hide the purchase button based on item status and ownership.
Form Handling
- Controlled inputs are used for the form fields.
- The
value
andonChange
props connect the input to the component's state.
Error Handling
- Try-catch blocks are used throughout the code to handle potential errors in asynchronous operations, especially during blockchain interactions.
The app.tsx
can become quite large so we can also refactor the code insite/src/app/components/
directory.
/components
- ListItem.tsx
- AvailableItems.tsx
- OwnedItems.tsx
/hooks
- useItems.ts
View the full-code here.
Also view the refactored code here.
This component demonstrates advanced React patterns, integration with blockchain technology, and modern UI practices. It showcases how to build a decentralized application frontend that interacts with a smart contract while providing a user-friendly interface.
Run the Development Server
Your Next.js application with Shadcn UI should now be running at http://localhost:3000
.
Now we should be able to list and item,buy and transfer ownership.
In this guide, we built a simple decentralized marketplace DApp on Linea, leveraging zkEVM technology for scalability and cost efficiency. We covered everything from setting up the environment to writing and deploying smart contracts, and integrating the frontend with Next.js and ShadcnUI.
As we continue to explore and expand on this foundational knowledge, consider the potential for further enhancements, such as integrating additional features or optimizing the user experience, bidding on items, auctions etc. The possibility of decentralized applications (DApps) are endless.
Happy coding!
The Resources:
- The github: https://github.com/meowyx/web3-marketplace-linea
- The Website: https://web3-marketplace-linea.vercel.app/