Building a Decentralized E-commerce Platform with QuickNode and Ethereum
Table of contents
- Introduction
- Prerequisites
- Setting Up the Development Environment
- Step 1: Install Truffle and Create a New Project
- Step 2: Create Smart Contracts
- Implementing the Smart Contract
- Step 1: Define Data Structures and State Variables
- Step 2: Implement Listing Products
- Step 3: Implementing Purchasing Products
- Deploying the Smart Contract
- Step 1: Configure Truffle
- Step 2: Deploy the Smart Contract
- Building the Frontend with React
- Frontend for Product Listing
- Resources
Introduction
Decentralized finance (DeFi) and blockchain technology have been revolutionizing various industries, and e-commerce is no exception. In this tutorial, we will walk you through the process of building a decentralized e-commerce platform using QuickNode, a leading blockchain-as-a-service provider, and Ethereum, a popular programmable blockchain. By the end of this tutorial, you'll have a functional platform that enables users to list and purchase products securely and transparently.
Prerequisites
To follow this tutorial, you'll need the following:
Basic knowledge of blockchain concepts
Node.js and npm installed on your machine
An Ethereum wallet and MetaMask browser extension
Solidity and web development knowledge (JavaScript, React)
Setting Up the Development Environment
Let's begin by setting up the development environment for our decentralized e-commerce platform.
Step 1: Install Truffle and Create a New Project
npm install -g truffle
truffle init
Step 2: Create Smart Contracts
In the contracts
directory, create a new file called Marketplace.sol
to define the smart contract for the marketplace.
// contracts/Marketplace.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Marketplace {
// Contract implementation here
}
Implementing the Smart Contract
In this section, we'll implement the smart contract with the necessary functions to list products and make purchases.
Step 1: Define Data Structures and State Variables
Add the following data structures and state variables to the Marketplace
contract:
// contracts/Marketplace.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Marketplace {
struct Product {
uint256 id;
string name;
string description;
uint256 price;
uint256 stock;
address seller;
}
uint256 public productCount;
mapping(uint256 => Product) public products;
}
Step 2: Implement Listing Products
Add a function to the Marketplace
contract that allows users to list their products for sale.
// contracts/Marketplace.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Marketplace {
// ... (previous code)
event ProductListed(uint256 id, string name, uint256 price, uint256 stock);
function listProduct(string memory _name, string memory _description, uint256 _price, uint256 _stock) public {
// Implement the listing logic here
// Ensure only authenticated users can list products
// Add the product to the products mapping and emit the ProductListed event
}
}
Step 3: Implementing Purchasing Products
Next, add a function to the Marketplace
a contract that allows users to purchase products.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Marketplace {
struct Product {
uint256 id;
address seller;
string name;
string description;
uint256 price;
uint256 stock;
}
uint256 public productCounter;
mapping(uint256 => Product) public products;
// Events for product listing and purchase
event ProductListed(uint256 id, string name, uint256 price, uint256 stock);
event ProductPurchased(uint256 id, string name, uint256 price, uint256 quantity);
// Function to list a new product for sale
function listProduct(string memory _name, string memory _description, uint256 _price, uint256 _stock) public {
productCounter++;
products[productCounter] = Product(productCounter, msg.sender, _name, _description, _price, _stock);
emit ProductListed(productCounter, _name, _price, _stock);
}
// Function to purchase a product
function purchaseProduct(uint256 _productId, uint256 _quantity) public payable {
Product memory product = products[_productId];
require(product.id > 0 && product.id <= productCounter, "Product not found");
require(_quantity > 0 && _quantity <= product.stock, "Invalid quantity");
require(msg.value >= product.price * _quantity, "Insufficient funds");
product.stock -= _quantity;
products[_productId] = product;
emit ProductPurchased(product.id, product.name, product.price, _quantity);
}
}
Deploying the Smart Contract
Now, let's deploy the smart contract to the Ethereum blockchain using Truffle.
Step 1: Configure Truffle
In the truffle-config.js
file, import the required packages and use the @truffle/hdwallet-provider
as the provider. Replace NETWORK_NAME
with the desired network name (e.g., ropsten, mainnet) and make sure to replace YOUR_MNEMONIC
with your Ethereum wallet's mnemonic or private key:
require('dotenv').config();
const HDWalletProvider = require('@truffle/hdwallet-provider');
const mnemonic = 'YOUR_MNEMONIC'; // Replace this with your Ethereum wallet's mnemonic or private key
const quicknodeApiKey = process.env.QUICKNODE_API_KEY;
const quicknodeEndpoint = process.env.QUICKNODE_ENDPOINT;
module.exports = {
networks: {
development: {
host: '127.0.0.1',
port: 8545,
network_id: '*',
},
ropsten: {
provider: () => new HDWalletProvider(mnemonic, quicknodeEndpoint),
network_id: 3,
gas: 5500000,
gasPrice: 20000000000, // 20 gwei (in wei)
},
// Add more networks as needed (e.g., mainnet)
},
// ... (other Truffle configurations)
};
Step 2: Deploy the Smart Contract
Run the following command to deploy the smart contract to the desired network:
truffle migrate --network NETWORK_NAME
Building the Frontend with React
Set up a React application in a new directory called client
. Install necessary dependencies and design the basic structure of the frontend.
npx create-react-app client
cd client
npm install web3 @truffle/hdwallet-provider dotenv
Create a new file web3.js
in the src
folder to connect the frontend with the Ethereum blockchain using Web3.
// src/web3.js
import Web3 from 'web3';
const getWeb3 = async () => {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum);
await window.ethereum.enable();
return window.web3;
} else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider);
return window.web3;
} else {
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!');
return null;
}
};
export default getWeb3;
In the App.js
file, import the Authenticate
component and implement the authentication logic using state.
// src/App.js
import React, { useState, useEffect } from 'react';
import getWeb3 from './web3';
import MarketplaceContract from './contracts/Marketplace.json';
import Authenticate from './components/Authenticate';
import Marketplace from './components/Marketplace';
const App = () => {
const [web3, setWeb3] = useState(null);
const [contract, setContract] = useState(null);
const [user, setUser] = useState(null);
const authenticateUser = async (username) => {
try {
const isAuthenticated = await contract.methods.authenticateUser(username).call();
if (isAuthenticated) {
setUser(username);
} else {
console.error('User not authenticated.');
}
} catch (error) {
console.error('Error authenticating user: ', error);
}
};
useEffect(() => {
const initWeb3 = async () => {
const web3Instance = await getWeb3();
if (web3Instance) {
setWeb3(web3Instance);
const networkId = await web3Instance.eth.net.getId();
const deployedNetwork = MarketplaceContract.networks[networkId];
if (deployedNetwork) {
const marketplaceInstance = new web3Instance.eth.Contract(
MarketplaceContract.abi,
deployedNetwork.address
);
setContract(marketplaceInstance);
} else {
console.error('Marketplace contract not deployed to the current network.');
}
}
};
initWeb3();
}, []);
return (
<div>
{user ? (
<Marketplace contract={contract} user={user} />
) : (
<Authenticate authenticateUser={authenticateUser} />
)}
</div>
);
};
export default App;
Frontend for Product Listing
Let's add the frontend to list products on the marketplace. In the Marketplace.js
file, implement a form to input product details and a button to list the product.
// src/components/Marketplace.js
import React, { useState } from 'react';
const Marketplace = ({ contract, user }) => {
const [productName, setProductName] = useState('');
const [productDescription, setProductDescription] = useState('');
const [productPrice, setProductPrice] = useState('');
const [productStock, setProductStock] = useState('');
const handleListProduct = async () => {
if (productName && productDescription && productPrice && productStock) {
try {
await contract.methods.listProduct(productName, productDescription, productPrice, productStock).send({
from: user,
});
console.log('Product listed successfully.');
// Update product listing UI or perform other actions after successful listing
} catch (error) {
console.error('Error listing product: ', error);
// Handle the error and display an appropriate message to the user
}
}
};
return (
<div>
<h2>Marketplace</h2>
<h3>List a Product</h3>
<input
type="text"
placeholder="Product Name"
value={productName}
onChange={(e) => setProductName(e.target.value)}
/>
<textarea
placeholder="Product Description"
value={productDescription}
onChange={(e) => setProductDescription(e.target.value)}
></textarea>
<input
type="number"
placeholder="Price (in ETH)"
value={productPrice}
onChange={(e) => setProductPrice(e.target.value)}
/>
<input
type="number"
placeholder="Stock"
value={productStock}
onChange={(e) => setProductStock(e.target.value)}
/>
<button onClick={handleListProduct}>List Product</button>
</div>
);
};
export default Marketplace;
Conclusion
Congratulations! You've built a decentralized e-commerce platform using QuickNode and Ethereum. Users can now authenticate themselves and list products securely on the platform. This tutorial provides a foundation for further enhancements, such as implementing secure payment mechanisms, real-time updates, and improving the user interface. You can explore more features like searching for products, product details, and purchasing products from the marketplace.
Remember to enhance security measures and thoroughly test your application before deploying it to a production environment. Building decentralized applications (dApps) is an exciting journey that offers transparency, security, and opportunities for innovative business models. Enjoy exploring the vast world of blockchain technology and DeFi applications!
Require assistance with your project or have inquiries? Feel free to reach out to us through this form, connect with us on Twitter @QuickNode, or ping us on Discord! We're here to help and support you every step of the way.
I'd love to connect with you on Twitter | LinkedIn | Portfolio.
Resources
QuickNode Developers Documentation
About QuickNode
QuickNode is building infrastructure to support the future of Web3. Since 2017, we've worked with hundreds of developers and companies, helping scale dApps and providing high-performance access to 23+ blockchains. Subscribe to our newsletter for more content like this, and stay in the loop with what's happening in Web3!