在蓬勃发展的Web3世界中,去中心化应用(dapps)已成为基础,提供安全、透明和无需信任的服务。其中,去中心化市场尤为突出,允许用户直接在区块链上买卖商品,有效消除中介。根据linea.mirror.xyz,本指南深入探讨了如何在Linea上构建一个简单的市场dapp,这是一种使用Layer 2 zkEVM技术,提供可扩展性和成本效率,同时保持以太坊的安全性。
理解市场Dapp架构
市场dapp的架构包括智能合约、前端和区块链集成。智能合约将处理例如物品列表、购买物品和所有权转移等功能。前端将作为用户界面,使买家和卖家能够与智能合约交互。与Linea区块链的交互将使用Metamask SDK以及Wagmi和Infura RPC提供商。
环境设置
首先,初始化一个monorepo来管理项目:
mkdir web3-marketplace-linea
cd web3-marketplace-linea
pnpm init
在根目录下创建一个pnpm-workspace.yaml
文件:
packages:
- 'packages/*'
工作空间结构包括:
packages
├── site # 使用Next.js、Tailwind CSS和Shadcn UI构建的前端
└── blockchain # 使用Hardhat的智能合约
接下来,在区块链目录中初始化一个Hardhat项目:
cd blockchain
npx hardhat init
选择TypeScript项目选项。
编写智能合约
智能合约将管理市场中的物品、所有权和交易:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
合同 Marketplace {
struct Item {
uint id;
string name;
uint price;
address payable seller;
address owner;
bool isSold;
}
uint public itemCount = 0;
mapping(uint => Item) public items;
mapping(address => uint[]) public ownedItems;
function listItem(string memory _name, uint _price) public {
require(_price > 0, "价格必须大于零");
itemCount++;
items[itemCount] = Item(itemCount, _name, _price, payable(msg.sender), msg.sender, false);
ownedItems[msg.sender].push(itemCount);
}
function purchaseItem(uint _id) public payable {
Item storage item = items[_id];
require(_id > 0 && _id <= itemCount, "物品不存在");
require(msg.value == item.price, "价格不正确");
require(!item.isSold, "物品已售出");
require(msg.sender != item.seller, "卖家不能购买自己的物品");
item.isSold = true;
item.seller.transfer(msg.value);
_transferOwnership(_id, item.seller, msg.sender);
}
function _transferOwnership(uint _id, address _from, address _to) internal {
Item storage item = items[_id];
item.owner = _to;
uint[] storage fromItems = ownedItems[_from];
for (uint i = 0; i < fromItems.length; i++) {
if (fromItems[i] == _id) {
fromItems[i] = fromItems[fromItems.length - 1];
fromItems.pop();
break;
}
}
ownedItems[_to].push(_id);
}
function transferItem(uint _id, address _to) public {
Item storage item = items[_id];
require(_id > 0 && _id <= itemCount, "物品不存在");
require(msg.sender == item.owner, "你不拥有此物品");
_transferOwnership(_id, msg.sender, _to);
}
function getItemsByOwner(address _owner) public view returns (uint[] memory) {
return ownedItems[_owner];
}
}
此合约便于去中心化市场,用户可以列出物品、购买物品和转移所有权,所有交易记录在区块链上。
部署智能合约
在ignition
文件夹中创建一个部署模块:
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
const MarketplaceModule = buildModule("MarketplaceModule", (m) => {
const marketplace = m.contract("Marketplace");
return { marketplace };
});
export default MarketplaceModule;
用你的Infura API密钥和账号私钥更新.env
文件:
INFURA_API_KEY=your_infura_api_key_here
ACCOUNT_PRIVATE_KEY=your_account_private_key_here
将合约部署到Linea测试网:
npx hardhat ignition deploy ignition/modules/Marketplace.ts --network linea-testnet
用Next.js和Shadcn UI进行前端开发
在site
目录中初始化Next.js项目:
mkdir site
cd site
npx create-next-app@latest .
在提示时选择TypeScript、ESLint、Tailwind CSS和App Router选项。安装Shadcn UI CLI:
npx shadcn-ui@latest init
创建一个wagmi.config.ts
文件以连接区块链:
import { http, createConfig } from "wagmi";
import { lineaSepolia } from "wagmi/chains";
import { metaMask } from "wagmi/connectors";
export const config = createConfig({
chains: [lineaSepolia],
connectors: [metaMask()],
transports: {
[lineaSepolia.id]: http(),
},
});
创建一个带有合约地址和ABI的constants.ts
文件:
export const CONTRACT_ADDRESS = "your_contract_address_here";
export const ABI = [/* ABI array here */];
开发前端组件并使用Wagmi和Metamask SDK将它们连接到智能合约。详细的说明和代码示例可以在完整的指南中找到,地址在linea.mirror.xyz。
运行开发服务器:
npm run dev
你的Next.js应用程序与Shadcn UI现在应该运行在http://localhost:3000。
在本指南中,我们在Linea上构建了一个简单的去中心化市场dapp,利用zkEVM技术实现可扩展性和成本效率。过程涵盖了从设置环境到编写和部署智能合约,以及与Next.js和Shadcn UI集成的前端开发。这些基础知识为进一步增强,例如集成其他功能或优化用户体验,奠定了基础。
Image source: Shutterstock