随着区块链技术的飞速发展,去中心化应用(DApp)正逐渐改变着我们与数字世界的交互方式,在众多公链和生态系统中,ZORA以其专注于NFT、文化创作和社区驱动的独特定位,吸引了开发者和创作者的目光,ZORA币($ZORA)作为其生态系统的核心代币,不仅用于交易和治理,更是在构建创新的DApp中扮演着重要角色,本教程将带你从零开始,一步步探索如何构建一个基于ZORA生态的DApp,让你快速上手这个充满活力的平台。

了解ZORA生态与$ZORA代币

在开始开发之前,对ZORA生态有一个基本的认识至关重要。

  1. ZORA是什么? ZORA最初是一个NFT协议和 marketplace,后来发展为一个更广泛的去中心化应用平台,它建立在以太坊(Ethereum)之上,并利用了Layer 2解决方案(如Optimism)来降低交易成本并提高速度,ZORA强调赋能创作者,让他们能够轻松地铸造、销售和管理自己的数字作品,同时为开发者提供了构建新型文化应用的基础设施。

  2. $ZORA代币的作用:

    • 治理: $ZORA持有者可以对ZORA协议的未来发展方向、参数调整等提案进行投票。
    • 交易与手续费: 在ZORA marketplace上进行NFT交易时,可能会用到$ZORA代币支付手续费或作为交易媒介。
    • 激励: 可能用于激励生态内的优质内容创作、开发者贡献或用户参与。
    • 访问权限: 某些基于Zora构建的DApp可能会要求持有一定数量的$ZORA代币才能访问特定功能。

开发前的准备工作

在动手编码之前,请确保你已经准备好以下工具和环境:

  1. 钱包: 你需要一个以太坊兼容的钱包,如MetaMask,确保钱包中已经有一些ETH(用于支付Gas费,尤其是在以太主网上)和一定数量的$ZORA代币(用于测试或实际交互)。
  2. 代码编辑器: Visual Studio Code (VS Code) 是目前最流行的选择,配合Solidity插件使用更佳。
  3. Node.js 和 npm/yarn: 用于安装和管理项目依赖,建议使用LTS版本的Node.js。
  4. 区块链浏览器: 如Etherscan,用于查看交易状态、合约代码等。
  5. 测试网络ETH: 在正式开发前,强烈建议在以太坊的测试网络(如Goerli、Sepolia)上进行开发和测试,你可以从测试水龙头获取免费的测试ETH。

搭建开发环境

我们将使用Hardhat作为以太坊开发环境,因为它提供了强大的编译、测试和部署功能。

  1. 创建项目目录:

    mkdir zora-dapp-tutorial
    cd zora-dapp-tutorial
  2. 初始化npm项目:

    npm init -y
  3. 安装Hardhat和相关依赖:

    npm install --save-dev hardhat
    npx hardhat

    在交互式命令行中选择 "Create a JavaScript project"(或TypeScript,如果你更熟悉的话),然后一路回车使用默认配置。

  4. 安装OpenZeppelin合约(可选但推荐): OpenZeppelin提供了经过审计的Solidity标准合约,如ERC721(NFT标准)、ERC20等,可以大大提高合约的安全性和开发效率。

    npm install @openzeppelin/contracts
  5. 配置MetaMask: 将你的MetaMask钱包切换到你打算使用的测试网络(如Goerli),并确保导入测试ETH。

构建你的第一个ZORA相关DApp(示例:简单的NFT展示与铸造DApp)

这个示例DApp将包含两个主要部分:一个智能合约(用于NFT的铸造逻辑)和一个前端界面(用于用户交互)。

编写智能合约

我们将创建一个简单的NFT合约,允许用户铸造一个固定的NFT集合。

  • contracts 目录下创建一个新的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 函数允许合约所有者(你)为指定地址铸造NFT。
    • totalSupply 函数返回已铸造的NFT数量。
  • 编译合约: 在项目根目录下运行:

    npx hardhat compile

    编译成功后,合约的ABI和字节码会生成在 artifacts/contracts/MyZoraNFT.sol/MyZoraNFT.json

编写测试脚本(可选但推荐)

test 目录下创建测试文件,myZoraNft.test.js,编写测试用例来验证合约的功能。

部署智能合约

  • scripts 目录下创建部署脚本,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 以连接到测试网络(例如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] : [],
        },
      },
    };

    你需要创建 .env 文件,并填入你的 GOERLI_URL(Alchemy或Infura的Goerli节点URL)和 PRIVATE_KEY(MetaMask中对应测试账户的私钥,注意保密!)。

  • 部署到测试网:

    npx hardhat run scripts/deploy.js --network goerli

    记录下部署后的合约地址。

开发前端DApp界面

我们将使用React和Ethers.js来构建前端。

  • 创建React应用:

    npx create-react-app frontend
    cd frontend
    npm install ethers
  • src 目录下修改 App.js 或创建新的组件:

    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 (wind
    随机配图
    ow.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);