隨著區(qū)塊鏈技術(shù)的飛速發(fā)展,去中心化應(yīng)用(DApp)正逐漸改變著我們與數(shù)字世界的交互方式,在眾多公鏈和生態(tài)系統(tǒng)中,ZORA以其專注于NFT、文化創(chuàng)作和社區(qū)驅(qū)動的獨(dú)特定位,吸引了開發(fā)者和創(chuàng)作者的目光,ZORA幣($ZORA)作為其生態(tài)系統(tǒng)的核心代幣,不僅用于交易和治理,更是在構(gòu)建創(chuàng)新的DApp中扮演著重要角色,本教程將帶你從零開始,一步步探索如何構(gòu)建一個基于ZORA生態(tài)的DApp,讓你快速上手這個充滿活力的平臺。
了解ZORA生態(tài)與$ZORA代幣
在開始開發(fā)之前,對ZORA生態(tài)有一個基本的認(rèn)識至關(guān)重要。
-
ZORA是什么? ZORA最初是一個NFT協(xié)議和 marketplace,后來發(fā)展為一個更廣泛的去中心化應(yīng)用平臺,它建立在以太坊(Ethereum)之上,并利用了Layer 2解決方案(如Optimism)來降低交易成本并提高速度,ZORA強(qiáng)調(diào)賦能創(chuàng)作者,讓他們能夠輕松地鑄造、銷售和管理自己的數(shù)字作品,同時為開發(fā)者提供了構(gòu)建新型文化應(yīng)用的基礎(chǔ)設(shè)施。
-
$ZORA代幣的作用:
- 治理: $ZORA持有者可以對ZORA協(xié)議的未來發(fā)展方向、參數(shù)調(diào)整等提案進(jìn)行投票。
- 交易與手續(xù)費(fèi): 在ZORA marketplace上進(jìn)行NFT交易時,可能會用到$ZORA代幣支付手續(xù)費(fèi)或作為交易媒介。
- 激勵: 可能用于激勵生態(tài)內(nèi)的優(yōu)質(zhì)內(nèi)容創(chuàng)作、開發(fā)者貢獻(xiàn)或用戶參與。
- 訪問權(quán)限: 某些基于Zora構(gòu)建的DApp可能會要求持有一定數(shù)量的$ZORA代幣才能訪問特定功能。
開發(fā)前的準(zhǔn)備工作
在動手編碼之前,請確保你已經(jīng)準(zhǔn)備好以下工具和環(huán)境:
- 錢包: 你需要一個以太坊兼容的錢包,如MetaMask,確保錢包中已經(jīng)有一些ETH(用于支付Gas費(fèi),尤其是在以太主網(wǎng)上)和一定數(shù)量的$ZORA代幣(用于測試或?qū)嶋H交互)。
- 代碼編輯器: Visual Studio Code (VS Code) 是目前最流行的選擇,配合Solidity插件使用更佳。
- Node.js 和 npm/yarn: 用于安裝和管理項目依賴,建議使用LTS版本的Node.js。
- 區(qū)塊鏈瀏覽器: 如Etherscan,用于查看交易狀態(tài)、合約代碼等。
- 測試網(wǎng)絡(luò)ETH: 在正式開發(fā)前,強(qiáng)烈建議在以太坊的測試網(wǎng)絡(luò)(如Goerli、Sepolia)上進(jìn)行開發(fā)和測試,你可以從測試水龍頭獲取免費(fèi)的測試ETH。
搭建開發(fā)環(huán)境
我們將使用Hardhat作為以太坊開發(fā)環(huán)境,因為它提供了強(qiáng)大的編譯、測試和部署功能。
-
創(chuàng)建項目目錄:
mkdir zora-dapp-tutorial cd zora-dapp-tutorial
-
初始化npm項目:
npm init -y
-
安裝Hardhat和相關(guān)依賴:
npm install --save-dev hardhat npx hardhat
在交互式命令行中選擇 "Create a JavaScript project"(或TypeScript,如果你更熟悉的話),然后一路回車使用默認(rèn)配置。
-
安裝OpenZeppelin合約(可選但推薦): OpenZeppelin提供了經(jīng)過審計的Solidity標(biāo)準(zhǔn)合約,如ERC721(NFT標(biāo)準(zhǔn))、ERC20等,可以大大提高合約的安全性和開發(fā)效率。
npm install @openzeppelin/contracts
-
配置MetaMask: 將你的MetaMask錢包切換到你打算使用的測試網(wǎng)絡(luò)(如Goerli),并確保導(dǎo)入測試ETH。
構(gòu)建你的第一個ZORA相關(guān)DApp(示例:簡單的NFT展示與鑄造DApp)
這個示例DApp將包含兩個主要部分:一個智能合約(用于NFT的鑄造邏輯)和一個前端界面(用于用戶交互)。
編寫智能合約
我們將創(chuàng)建一個簡單的NFT合約,允許用戶鑄造一個固定的NFT集合。
-
在
contracts目錄下創(chuàng)建一個新的Solidity文件,MyZoraNFT.sol。 -
編寫合約代碼:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract MyZoraNFT is ERC721, Ownable { uint256 private _tokenCounter; constructor() ERC721("MyZoraNFT", "MZORA") { _tokenCounter = 0; } function mint(address to) public onlyOwner { _safeMint(to, _tokenCounter); _tokenCounter++; } function totalSupply() public view returns (uint256) { return _tokenCounter; } }- 這個合約繼承自ERC721和Ownable。
mint函數(shù)允許合約所有者(你)為指定地址鑄造NFT。totalSupply函數(shù)返回已鑄造的NFT數(shù)量。
-
編譯合約: 在項目根目錄下運(yùn)行:
npx hardhat compile
編譯成功后,合約的ABI和字節(jié)碼會生成在
artifacts/contracts/MyZoraNFT.sol/MyZoraNFT.json。
編寫測試腳本(可選但推薦)
在 test 目錄下創(chuàng)建測試文件,myZoraNft.test.js,編寫測試用例來驗證合約的功能。
部署智能合約
-
在
scripts目錄下創(chuàng)建部署腳本,deploy.js:async function main() { const MyZoraNFT = await ethers.getContractFactory("MyZoraNFT"); const myZoraNFT = await MyZoraNFT.deploy(); await myZoraNFT.deployed(); console.log("MyZoraNFT deployed to:", myZoraNFT.address); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); }); -
修改
hardhat.config.js以連接到測試網(wǎng)絡(luò)(例如Goerli):require("@nomicfoundation/hardhat-toolbox"); require("dotenv").config(); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.20", networks: { goerli: { url: process.env.GOERLI_URL || "", accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], }, }, };你需要創(chuàng)建
.env文件,并填入你的GOERLI_URL(Alchemy或Infura的Goerli節(jié)點(diǎn)URL)和PRIVATE_KEY(MetaMask中對應(yīng)測試賬戶的私鑰,注意保密?。?。 -
部署到測試網(wǎng):
npx hardhat run scripts/deploy.js --network goerli
記錄下部署后的合約地址。
開發(fā)前端DApp界面
我們將使用React和Ethers.js來構(gòu)建前端。
-
創(chuàng)建React應(yīng)用:
npx create-react-app frontend cd frontend npm install ethers
-
在
src目錄下修改App.js或創(chuàng)建新的組件:import { useState, useEffect } from 'react'; import { ethers } from 'ethers'; import MyZoraNFTArtifact from '../artifacts/contracts/MyZoraNFT.sol/MyZoraNFT.json'; // 確保路徑正確 function App() { const [account, setAccount] = useState(''); const [contract, setContract] = useState(null); const [nftContractAddress, setNftContractAddress] = useState('YOUR_DEPLOYED_CONTRACT_ADDRESS_HERE'); // 替換為你的合約地址 const [totalSupply, setTotalSupply] = useState(0); const connectWallet = async () => { if (window.ethereum) { try { const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); setAccount(accounts[0]); const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); const nftContract = new ethers.Contract(nftContractAddress, MyZoraNFTArtifact.abi, signer); setContract(nftContract); const supply = await nftContract.totalSupply(); setTotalSupply(supply.toString()); } catch (error) { console.error("Error connecting wallet:", error);