如何在Arbitrum Nova上创建1万个NFT集合

本文详细介绍了如何在Arbitrum Nova链上创建并部署一个包含10000个NFT的集合。内容涵盖了环境搭建、NFT合约的创建与部署、元数据生成与上传IPFS、以及如何在NFT市场上展示和销售NFT。通过本指南,读者可以学习到NFT开发和部署的全流程。

概述

想要创建一个 10,000 个 NFT 的集合吗?本指南将带你踏上在 Arbitrum Nova 上实现你的 10,000 件 NFT 集合之旅。你将学习如何创建元数据,使用 Hardhat 部署 NFT 智能合约,以及铸造独特的代币,以便在像 TofuNFT 这样的知名 NFT 市场上展示。

你需要的

你将要做的

  • 使用 Hardhat 创建 NFT 合约
  • 为你的 NFT 集合创建图像和元数据
  • 测试你的 NFT 合约并部署到 Arbitrum Nova 上
  • 铸造一个 NFT 并在 NFT 市场上查看它

Arbitrum Nova 概述

Arbitrum Nova 是以太坊的 Layer 2 扩展解决方案,旨在为去中心化应用程序提供超快和廉价的交易。它结合使用 AnyTrust 技术和数据可用性委员会(DAC)来实现其目标,并且比 Arbitrum One 便宜得多。

AnyTrust 是 Arbitrum Nitro 技术的一种变体,它通过假定较小程度的信任来降低成本。AnyTrust 利用第三方数据可用性委员会 (DAC) 来存储数据并按需提供。QuickNode 作为领先的区块链服务提供商,被选为 Arbitrum Nova 的 DAC 委员会成员(与 Google Cloud、Reddit 和 Consensys 一起)。作为 DAC 成员,QuickNode 运行数据可用性服务器,允许通过 REST API 按需提供交易批量数据。有关 DAC 的更多信息,请查看这篇 QuickNode 博客文章

Arbitrum Nova 具有各种用例,例如 Web3 游戏和社交基础设施,但在本指南中,我们将专门介绍 NFT(Non-Fungible 代币)。这些独特的数字资产近年来日益普及,并且有几个原因让人们希望在 Arbitrum Nova 上开发 NFT:

  • 超低的交易成本
  • 快速交易和快速出块时间
  • 与其他 EVM 链的互操作性

这些优势对于具有大量交易量的项目(如游戏开发、社交项目和去中心化金融 (DeFi))也很有利。

如果你想了解更多关于 Arbitrum Nova 与 Arbitrum One 和其他区块链相比的优势,请查看此 QuickNode 指南

设置开发环境

步骤 1:使用 QuickNode 访问 Arbitrum Nova

你需要一个 API 端点才能与 Arbitrum Nova 链通信。欢迎你使用公共节点或部署和管理你自己的基础设施;但是,如果你想要快 8 倍的响应时间,你可以将繁重的工作交给我们。在此处注册一个帐户 here

登录后,单击创建端点,然后选择 Arbitrum Nova Mainnet 链。

Endpoint

创建端点后,请随时保存 HTTP Provider URL,因为稍后在配置你的 .env 时需要它。

步骤 2:创建一个钱包并用 ETH 充值

在本指南中,我们将使用 Torus Wallet,这是一个支持多个链和网络的非托管钱包,包括以太坊、Arbitrum OneArbitrum Nova 和其他 EVM 相关链。请记住,为了在 Arbitrum Nova Mainnet 上部署,你需要有实际资金 (ETH) 来支付交易费用。这些费用应该很小,不应超过 0.25 美元。你可以在像 Uniswap 这样的去中心化交易所或在像 Coinbase 这样的传统交易所购买 ETH。你可以使用 Arbitrum Nova Bridge 将资金转移到 Arbitrum Nova 上。

要开始,请转到 Torus 并按照说明生成私钥。

Torus

在继续本指南的技术方面之前,请确保你的 Arbitrum Nova 主网地址上有足够的资金来支付合约部署和交互费用。如果需要桥接资金,你可以使用 Arbitrum Nova bridge

步骤 3:创建一个新项目

要使用 Hardhat,你首先需要在计算机上安装 Node.js。你可以从官方网站下载它 nodejs.org

打开一个终端并检查是否安装了 Node.js 并且版本为 18>:

node -v

导航到要创建项目的目录。在本指南中,我们将创建一个名为 10k-collection 的文件夹:

mkdir 10k-collection

导航到你刚创建的文件夹中,然后使用以下命令初始化一个新的 npm 项目:

npm init -y

然后,通过运行以下命令安装 Hardhat:

npm install --save-dev hardhat

--save-dev 将其添加到 package.json 中的 devDependencies 列表中

现在,我们将通过运行以下命令来初始化 Hardhat 项目:

npx hardhat create

当提示要创建的项目类型时,选择第三个选项(即,创建一个空的 hardhat 配置文件)。

这将创建一个具有默认 Hardhat 项目结构的新目录。接下来,我们需要为我们的 10k-collection 创建所需的文件夹。

mkdir contracts
mkdir test
mkdir scripts

步骤 5:安装必要的库

在项目目录中,运行以下命令来安装项目所需的依赖项:

npm install dotenv @openzeppelin/contracts @nomicfoundation/hardhat-toolbox

步骤 6:设置你的配置文件以进行部署

为了保护你的私钥和 RPC URL(以防你在 Github 上发布你的代码),我们将创建一个 .env 文件来存储凭据。将推送到 Github 时,不应包含此文件。

在你的主项目目录中,运行以下终端命令来创建 .env 文件:

echo > .env

打开文件并输入以下变量。然后,使用你的实际凭据更新占位符值。记住保存文件!

RPC_URL=<YOUR_RPC_URL>
PRIVATE_KEY=<YOUR_PRIVATE_KEY>

接下来,我们将设置 hardhat.config.js 文件。打开文件并输入以下代码。

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

module.exports = {
  solidity: "0.8.17",
  networks: {
    nova: {
      url: process.env.RPC_URL,
      accounts: [process.env.PRIVATE_KEY]
    }
  }
};

记住保存文件!在下一节中,我们将为我们的 10K NFT 集合创建图像和元数据。

创建元数据并上传到 IPFS

在本节中,我们将为 10K NFT 集合创建元数据。

具体来说,我们将使用 Figma 和这个 Github repository 用于生成图像资源和元数据(感谢编写它的人!)。请注意,你可以使用其他工具来创建元数据,这不是唯一的方法。

为了创建具有不同图像的 10,000 个 NFT,你至少需要七个图层,每个图层有四个不同的选项。查看此 Figma file 以查看示例。请注意,此 Figma 文件仅包含三个图层,其余四个已在我们要使用的存储库中创建。或者,你也可以跳过此步骤,仅使用 Github repository 中找到的示例资源。

将图像资源导出到你的 PC 后,克隆以下存储库并在你选择的代码编辑器中打开它。

git clone https://github.com/manuelpires/nft-collection-generator/

然后,使用以下命令安装所需的依赖项:

npm install

如果你正在运行 Mac OSX 并且上面的安装命令抛出错误,则你可能需要首先安装以下库:

brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman

然后安装 canvas:

npm i canvas

现在,创建两个文件夹 metadataimages

mkdir metadata && mkdir images

然后,导航到 traits 目录并为每个图层创建文件夹。在我们的示例中,我们为 arrowscirclesstars 创建了一个文件夹。

注意:如果你仅使用 traits 文件夹中已有的示例图像,请忽略此步骤并跳至运行 node index.js 命令。

images dir

之后,打开 config.js 文件并将每个图层添加到 ORDERED_TRAITS_LIST 对象。一个例子如下所示:

  {
    type: "Square",
    options: [\
      {\
        image: "./traits/square/bright-coral.png",\
        value: "Bright Coral",\
        weight: 1,\
      },\
      {\
        image: "./traits/square/liliac.png",\
        value: "Liliac",\
        weight: 1,\
      },\
      {\
        image: "./traits/square/pumpkin.png",\
        value: "Pumpkin",\
        weight: 1,\
      },\
      {\
        image: "./traits/square/spring.png",\
        value: "Spring",\
        weight: 1,\
      },\
      {\
        weight: 1,\
      },\
    ],
  },

请注意,图层是按顺序添加的,因此请注意你使用的顺序。weight 选项相对于同一选项数组中其他项的权重,它应该是一个至少为 1 的整数。如果在某个选项中放置权重 10,则它被选择的概率应该是同一数组中权重等于 1 的选项的 10 倍。

使用所有元数据和图像引用设置 config.js 并且安装了所需的依赖项后,通过运行以下命令生成元数据和图像:

node index.js

创建图像和元数据后,请花几分钟时间查看它们,以确保它们按预期生成。将图像和元数据上传到 IPFS 后,我们将需要用我们的实际元数据链接替换基本 URL,因此请随时保存此文件夹。

将元数据和图像发布到 IPFS

现在我们已经创建了元数据和图像,我们需要将它们上传到 IPFS,这是一个协议、超媒体和文件共享点对点网络,用于在分布式文件系统中存储和共享数据。我们将使用 IPFS 而不是中心化存储解决方案(如 Amazon),因为我们希望我们的 NFT 集合与它的去中心化属性保持一致。但是请注意,IPFS 可以免费使用,但有时可能很慢,并且你需要主动 pinning 你的内容(即,保持你的 IPFS 节点运行)才能保持你的元数据可检索。

或者,你也可以使用像 Pinata (免费和付费版本)或 NFT.Storage(免费但存储有限)这样的服务轻松地将数据上传到 IPFS 并保持你的内容 pinned 并更快地检索,但它们有存储限制并且可能需要付费。

在任何情况下,你都需要将你的元数据上传到一个文件夹中,以便它对该目录中的所有文件具有相同的根路径。

例如:

https://ipfs.io/ipfs/bafybeidhtkrvmboa4pel3i3asl57rgmrtai4zelpoeccfulw7qxqbhwyw4/metadata/

上面的 URL 指向 IPFS 上的一个文件夹,该文件夹包含 NFT 元数据的文件。你也可以在路径末尾添加一个数字(例如,/metadata/1)来查看每个 NFT 的元数据。标准化此数据非常重要,这样应用程序可以更轻松地显示你的 NFT 并与之交互。

首先,我们将使用以下 link 安装 IPFS。你可以通过多种方式访问 IPFS;但是,我们将通过 Kubo binary 安装。

然后,打开一个新的终端窗口(Mac 上为 CMD + T)并检查是否安装了 IPFS:

ipfs --version

接下来,我们将启动 IPFS 节点,我们将使用它来 pinning 到 IPFS 网络并使其保持持久。

ipfs init

你应该看到类似以下内容:

initializing ipfs node at /Users/user/.ipfs
> generating 2048-bit RSA keypair...done
> peer identity: Qmcpo2iLBikrdf1d6QU6vXuNb6P7hwrbNPW9kLAH8eG67z
> to get started, enter:
>
>   ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme

要将我们的 IPFS 节点联机,请运行以下命令:

ipfs daemon

记下守护程序正在侦听的 TCP 端口

然后,打开另一个终端窗口。如果你已连接到网络,则在运行以下命令时,你应该能够看到你的对等方的 IPFS 地址:

ipfs swarm peers

你可以通过运行以下命令来测试你的 IPFS 是否可以从网络请求数据:

ipfs cat /ipfs/QmSgvgwxZGaBLqkGyWemEDqikCqU52XxsYLKtdy3vGZ8uq > ~/Desktop/spaceship-launch.jpg

如果你能够下载图像,那就太好了!我们现在可以将我们的图像和元数据上传到 IPFS。

在你的项目根目录中,运行以下 IPFS 命令来 pinning 图像文件夹:

ipfs add -r images/

输出的最后一行将显示根目录的 CID,它是你上传的文件夹的顶级目录。你可以通过将 CID 添加到 IPFS 网关 URL “https://ipfs.io/ipfs/”来访问此 IPFS 地址上的文件夹

IPFS CID dir terminal

现在我们的图像已上传,从你的根 images/ 文件夹中获取 CID 哈希并返回到 nft-collection-generator 存储库。使用以下终端命令一次性替换所有占位符 URL 为你的实际图像 URL:

find metadata -type f -exec perl -pi -e 's#https://base-uri-to-my-nft-images.com/#https://ipfs.io/ipfs/{CID}/#g' {} +

切记将上面命令中的 {CID} 替换为你上传的 images/ 文件夹中的 IPFS CID 哈希!

最后,你的元数据文件中的内容应如下所示:

{
  "tokenId": 0,
  "name": "KT0",
  "description": "KT Collection",
  "image": "https://ipfs.io/ipfs/Qma5p2daHfdui4keZjMrJpgmL7JRjoZ6J5GcyLPUcmTTuT/0.png",
  "attributes": [\
    {\
      "trait_type": "Background",\
      "value": "Robin"\
    },\
    {\
      "trait_type": "Square",\
      "value": "Spring"\
    },\
    {\
      "trait_type": "Triangle",\
      "value": "Green"\
    },\
    {\
      "trait_type": "Circle",\
      "value": "Blue"\
    },\
    {\
      "trait_type": "Arrows",\
      "value": "Up"\
    }\
  ]
}

接下来,我们需要将我们的元数据(JSON 文件)捆绑到一个 .CAR(内容寻址存档)文件中。你可以使用 ipfs car 命令来执行此操作。

运行以下命令来创建一个包含 JSON 文件的 CAR 文件:

npx ipfs-car --pack metadata/

系统可能会要求你安装外部库

现在我们的 JSON 已捆绑到 .CAR 文件中,我们将使用以下命令将其 pinning 到 IPFS:

ipfs dag import metadata.car

你应该看到一个类似于:

Pinned root bafybeihzssbfdo6cmprolorfimhda4yapkzkyukffsteta6exwcr4nipzi success

你可以通过转到你上传中引用的 CID 来检查你的元数据是否可访问。切记在 URL 末尾添加 /metadata/ 路径:

https://ipfs.io/ipfs/{CID}/metadata/

metadata on IPFS

你还可以通过本地 IPFS 节点(守护程序)访问 IPFS URL。根据网络状态,由于公共网关过载或难以访问你,curl 可能需要一段时间。要查看本地网关上的对象,请尝试“http://127.0.0.1:8080/ipfs/{CID}”。对于公共网关,请使用 https://ipfs.io/ipfs/{CID}

注意,使用 IPFS Gateway checker 查看当前最快的网关。

在下一节中,你将开发你的 NFT 合约!

创建 NFT 合约

在 contracts 目录中创建一个名为 NFT.sol 的新文件。

打开该文件并输入以下代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

// 用于创建 10k 代币的合约,继承自 ERC721 和 Ownable
contract KTokens is ERC721, Ownable {
    // 最大供应量
    uint256 public constant MAX_SUPPLY = 10000;

    // 当前供应量
    uint256 public totalSupply = 0;

    // 使用 Counters 库进行代币 ID 计数
    using Counters for Counters.Counter;

    // 私有变量,用于跟踪代币 ID
    Counters.Counter private _tokenIdCounter;

    // 构造函数,用于使用名称“10K Tokens”和符号“10KT”初始化合约
    constructor() ERC721("10K Tokens", "10KT") {}

    // 内部函数,用于返回合约的基本 URI
    function _baseURI() internal pure override returns (string memory) {
        return "https://ipfs.io/ipfs/{CID}/metadata/";
    }

    // 用于铸造新代币的函数,只能由合约所有者调用
    function safeMint(address to) public onlyOwner {
        // 要求当前供应量小于最大供应量
        require(totalSupply <= MAX_SUPPLY, "Maximum supply reached");
        // 递增总供应量变量
        totalSupply++;
        // 获取当前代币 ID
        uint256 tokenId = _tokenIdCounter.current();
        // 递增代币 ID 计数器
        _tokenIdCounter.increment();
        // 将代币铸造到指定的地址
        _safeMint(to, tokenId);
    }
}

花几分钟时间查看代码注释以更好地理解逻辑

这里未显示但继承自我们从 OpenZeppelin 导入的 ERC721.sol 合约的是 tokenURI 函数。这个只读函数接受一个 tokenId 并返回一个 URL,该 URL 应该指向该特定代币的元数据。

你需要使用你在上传元数据目录时获得的 CID 编辑 _baseURI() 函数中的占位符(https://ipfs.io/ipfs/{CID})。如果不是在使用 IPFS,此 CID 或 URL 应该指向你的元数据所在的目录。切记在转到下一步之前保存文件!

接下来,你需要编译 NFT 合约。这需要将 Solidity 代码编译成字节码,然后将其部署到区块链上。

要编译合约,请运行以下 Hardhat 命令:

npx hardhat compile

你应该会看到类似以下消息:

Compiled 13 Solidity files successfully

在下一节中,我们将为 NFT 合约创建测试,以确保在部署到 Arbitrum Nova 主网时一切顺利。

测试 NFT 合约

在本节中,我们将创建测试来检查我们的 NFT 合约的行为。测试我们的 NFT 很重要,因为它允许开发人员确保他们的智能合约按预期运行,并且在部署到区块链之前没有错误。这至关重要,因为一旦部署了合约,就无法修改或删除它,因此任何错误或问题都将是永久性的。此外,测试可以帮助防止合约中潜在的安全漏洞,恶意行为者可能会利用这些漏洞。

tests 目录中,创建一个名为 NFT.js 的文件并输入以下代码:

const { expect } = require("chai");

describe("KTokens", () => {
    let kTokens;
    let owner;

    beforeEach(async function () {
        // 从 ethers 检索默认帐户
        [owner] = await ethers.getSigners();

        // 一个获取合约实例并在本地部署它的助手
        const KTokens = await ethers.getContractFactory("KTokens");
        kTokens = await KTokens.deploy();
    });

    it("should have the correct name and symbol", async () => {
        expect(await kTokens.name()).to.equal("10K Tokens");
        expect(await kTokens.symbol()).to.equal("10KT");
    });

    it("should be able to mint new tokens", async () => {
        // 铸造一个新的代币
        await kTokens.safeMint(owner.address);
        expect(await kTokens.ownerOf(0)).to.equal(owner.address);
    });
});

花几分钟时间查看代码注释以更好地理解逻辑

要执行测试文件,请运行以下命令:

npx hardhat test

你应该看到以下输出:

KTokens
    ✔ should have the correct name and symbol
    ✔ should be able to mint new tokens

  2 passing (1s)

在下一节中,我们将把 10K NFT 集合部署到 Arbitrum Nova

部署 NFT 合约

在你的 scripts 文件夹中,创建一个名为 deploy.js 的文件:

echo > scripts/deploy.js

然后,打开该文件并输入以下代码:

const hre = require("hardhat");

async function deploy() {
    // 部署合约
    const NFT = await hre.ethers.getContractFactory("KTokens");
    const nft = await NFT.deploy();

    // 打印已部署合约的地址
    console.log("NFT 合约部署于:", nft.address);
}

deploy()
    .then(() => console.log("部署完成"))
    .catch((error) => console.error("部署合约时出错:", error));

此文件将包含将我们的合约部署到 Arbitrum Nova Mainnet 所需的逻辑。

要部署合约,请在你的终端中运行以下 hardhat 命令:

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

nova 对象是我们在 hardhat.config.js 中创建的对象

你应该看到一个包含你已部署合约地址的输出。

NFT 合约部署于:0xf18802cb61EF336E30c5B93a7c9C961b1e80BeDE
部署完成

铸造 NFT 并在 NFT 市场上查看它

现在我们的 NFT 合约已部署,让我们铸造一个 NFT 并在 NFT 市场上查看它。为了本指南的目的,我们将仅铸造 1 个 NFT,但你可以使用相同的流程来铸造多个 NFT。

在你的 scripts 文件夹中创建一个 mint.js 文件:

echo > scripts/mint.js

然后,打开该文件并输入以下代码:

const hre = require("hardhat");

async function main() {
    let owner;

    // 从 ethers 检索默认帐户
    [owner] = await ethers.getSigners();

    // 获取 NFT 合约的合约工厂
    const NFT = await ethers.getContractFactory("KTokens");

    // 在指定的地址附加到已部署的合约
    const nft = await NFT.attach(
      "DEPLOYED_CONTRACT_ADDRESS" // 你的已部署合约地址
    );

    // 调用 safeMint 函数以更新值
    let safeMintTx = await nft.safeMint(owner.address)
    console.log("safeMint 函数调用。等待确认...")

    // 等待 3 个区块以确认交易
    await safeMintTx.wait(confirm=3);

    // 获取最新的 token Supply
    let tokenSupply = (await nft.totalSupply()).toString()

    // 减一,因为 tokenID 从零开始
    let tokenIdInt = parseInt(tokenSupply) - 1

    // 获取已铸造 tokenID 的所有者
    let tokenOwner = await nft.ownerOf(tokenIdInt);

    console.log(`Token ID ${tokenId} - tokenOwner ${tokenOwner}`)
}

// 启动脚本并处理任何错误
main()
    .then(() => console.log("脚本完成"))
    .catch((error) => console.error("运行脚本时出错:", error));

铸造后,你可以转到像 tofuNFT.com 这样的 NFT 市场,这是一个支持 Arbitrum Nova 的多链 NFT 市场,并放入你的钱包地址以查看 NFT。

minted NFT on marketplace

如果你对一次性铸造 10,000 个代币感兴趣,请查看本指南 How to Mint NFTs Using the ERC721A Implementation

Arbitrum 生态系统

现在你已经在 Arbitrum Nova 上部署了你的第一个智能合约,你可以探索 Arbitrum Nova 链提供的一些资源:

更多资源

如果你想继续了解 Arbitrum Nova 和智能合约,请查看以下资源:

结论

恭喜!你现在拥有部署 10K NFT 集合的技能!

你将 Arbitrum Nova 用于什么?我们很想看看你在创建什么!在 DiscordTwitter 上与我们分享你的应用程序。如果你对此指南有任何反馈或问题,我们很乐意听取你的意见!

  • 原文链接: quicknode.com/guides/arb...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。