主页 > imtoken官方版 > 建立你自己的以太坊 NFT 收藏(二)

建立你自己的以太坊 NFT 收藏(二)

imtoken官方版 2023-10-05 05:12:33

另外——从头开始编写 NFT 合约太疯狂了! 您可以探索我们从这里继承的“ERC721”合约 [6]。

让我们使用 makeAnEpicNFT 函数一步步过一遍。

uint256 newItemId = _tokenIds.current();

_tokenIds 到底是什么? 还记得毕加索的例子吗? 他有 100 个 NFT 草图,分别命名为 Sketch #1、Sketch #2、Sketch #3 等。这些都是唯一标识符。

同样,我们使用 _tokenIds 来跟踪 NFT 的唯一标识符,它只是一个数字! 当我们声明private _tokenIds时,它会自动初始化为0。所以当我们第一次调用makeAnEpicNFT时,newItemId为0,再次运行时,newItemId将为1,以此类推!

_tokenIds 是一个状态变量,这意味着如果我们更改它,该值将直接存储在合约中。

_safeMint(msg.sender, newItemId);

当我们执行 _safeMint(msg.sender, newItemId) 时,它几乎是在说:“将 ID 为 newItemId 的 NFT 发送给地址为 msg.sender 的用户”。 这里,msg.sender 是 Solidity [7] 提供的一个变量,它允许我们轻松访问调用合约的人的公共地址。

这里最好的部分是它是获取用户公共地址的超级安全方式。 保持公共地址本身的私密性不是问题,它是公开的! ! 但是,通过使用 msg.sender 你不能“伪造”别人的公共地址,除非你有他们的钱包凭证并代表他们调用合约!

你不能匿名调用合约,你需要连接你的钱包。 这几乎就像“登录”并通过身份验证。

_tokenIds.increment();

然后我们覆盖 ERC721.sol 中的 tokenURI() 函数,它将设置 NFT 的唯一标识符以及与该标识符关联的数据。 我们从字面上设置了使 NFT 有价值的实际数据。 在这种情况下,我们将其设置为 blah,这……真的毫无价值;)。 它也不遵循 ERC721 标准。 稍后我们将更详细地介绍 tokenURI。

function tokenURI(uint256 _tokenId) public view override returns (string memory);

NFT生成后,我们使用_tokenIds.increment()增加tokenIds(这是OpenZeppelin给我们的函数)。 它可以确保下次铸造 NFT 时,它具有不同的 tokenIds 标识符。 没有人可以拥有已经铸造的 tokenId。

在本地生成 tokenURI

tokenURI 是实际 NFT 数据所在的位置。 它通常链接到一个名为元数据的 JSON 文件,如下所示:

{
    "name""Spongebob Cowboy Pants",
    "description""A silent hero. A watchful protector.",
    "image""https://i.imgur.com/v7U019j.png"
}

您可以自定义它,但几乎每个 NFT 都有名称、描述以及指向视频、图像等的链接。 它甚至可以有自定义属性! 注意元数据的结构,如果你的结构不符合 OpenSea 要求 [8],你的 NFT 将在网站上出现损坏。

这些都是 ERC721 标准的一部分,它允许人们在非功能数据之上构建网站。 例如,OpenSea [9] 是一个查看 NFT 的平台。 此外,OpenSea 上的每一个 NFT 都遵循 ERC721 元数据标准,这使得人们可以轻松查看他们的 NFT。 想象一下,如果每个人都遵循自己的 NFT 标准并按照自己的意愿构建元数据,那会是怎样的混乱局面!

我们可以复制 Spongebob Cowboy Pants 的 JSON 元数据并将其粘贴到这个 [10] 网站中。 这个网站只是一个方便人们存放JSON数据的地方以太坊创建时间,现在我们将用它来存放NFT数据。 当你点击保存时,你会得到一个 JSON 文件的链接,(例如我的是 [11]。一定要先测试你的链接以确保它有效!

注意:我希望您创建自己的 JSON 元数据,而不仅仅是复制我的。 使用您自己的图片、名称和描述。 也许你想让你的 NFT 成为你最喜欢的动画角色、最喜欢的乐队,等等!! 定制。 别担心,我们会在未来改变这一点!

如果您决定使用自己的图片,请确保 URL 直接指向实际图片,而不是托管图片的网站! 一个直接的 Imgur 链接看起来像这样 - 它不是。 最简单的判断方法是检查 URL 是否以图像扩展名结尾,例如 .png 或 .jpg。 您可以右键单击 imgur 图像和“复制图像地址”,这将为您提供正确的 URL。

现在,让我们转到我们的智能合约并更改 tokenURI() 中的一行。 代替:

return "blah";

我们实际上要将 URL 设置为我们的 JSON 文件链接。

return "INSERT_YOUR_JSON_URL_HERE";

我们还可以添加一个console.log来帮助我们查看NFT的铸造时间和铸造对象!

console.log("An NFT w/ ID %s has been minted to %s", newItemId, msg.sender);

这就是您的 tokenURI 函数现在的样子。 _exists 是一个内置函数,用于验证合约中 tokenId 是否存在。 您可以在此处了解更多信息 [12]。

function tokenURI(uint256 _tokenId) public view override returns (string memory) {
  require(_exists(_tokenId));
  console.log("An NFT w/ ID %s has been minted to %s", _tokenId, msg.sender);
  return "INSERT_YOUR_JSON_URL_HERE";
}

在本地铸造 NFT

从这里开始,我们需要做的就是更改我们的 run.js 文件以实际调用我们的 makeAnEpicNFT() 函数。

以下代码是我们需要做的全部:

const main = async () => {
  const nftContractFactory = await hre.ethers.getContractFactory('MyEpicNFT');
  const nftContract = await nftContractFactory.deploy();
  await nftContract.deployed();
  console.log("Contract deployed to:", nftContract.address);

  // Call the function.
  let txn = await nftContract.makeAnEpicNFT()
  // Wait for it to be mined.
  await txn.wait()

  // Mint another NFT for fun.
  txn = await nftContract.makeAnEpicNFT()
  // Wait for it to be mined.
  await txn.wait()

};

const runMain = async () => {
  try {
    await main();
    process.exit(0);
  } catch (error) {
    console.log(error);
    process.exit(1);
  }
};

runMain();

当我们运行以下命令时:

npx hardhat run scripts/run.js

我们会看到:

以太坊创建合约的过程_以太坊创建时间_以太坊区块生成时间

繁荣! 我们刚刚在本地为自己铸造了 ID 为 0 的 NFT! 所以以太坊创建时间,我们知道代码可以正常工作,没有任何错误。 太棒了 你总是想使用 run.js 来确保事情在本地运行而不会崩溃,这是你自己的小测试场!

所以,现在每次有人用这个功能铸造一个 NFT,它总是同一个 NFT——“海绵宝宝牛仔裤”! 我们将在下一节中学习如何更改此设置,以便与您一起铸造 NFT 的每个人都将获得一个随机的、独特​​的 NFT。

现在,让我们继续下一步——部署到测试网。

部署到 Goerli 并在 OpenSea 上查看

由于 OpenSea 不支持 Goerli,我们不得不寻找替代方案。 当部署到 Goerli 时,您可以登录 OpenSea [13] 查看您的 NFT。 当我们使用 run.js 时,它只是在本地工作。

下一步是测试网,您可以将其视为“彩排”练习环境。 当我们部署到测试网时,我们实际上可以在线查看我们的 NFT,我们离提交给真实用户又近了一步。

贸易

所以当我们想要执行一个改变区块链的操作时,我们称之为交易。 例如,向某人发送 ETH 是一笔交易,因为我们正在更改帐户余额。 在我们的合同中做一些更新变量的事情也被认为是一个交易,因为我们正在改变数据。 铸造 NFT 是一项交易,因为我们将数据保存在合约上。

部署智能合约也是一种交易。

请记住,区块链是去中心化的。 它是世界各地的矿工通过大量计算机运行的区块链的副本。

当我们部署合约时,我们需要告诉所有这些矿工,“嘿,这是一个新的智能合约,请将我的智能合约添加到区块链中,然后也告诉其他人”。

这就是 QuickNode [14] 发挥作用的地方。

QuickNodes 基本上帮助我们广播我们的合同创建交易,以便矿工能够尽快获得它。 一旦交易被挖掘,它就会作为合法交易广播到区块链。 从那里,每个人都可以更新他们的区块链副本。

情况很复杂。 而且,如果您不完全理解它,请不要担心。 当您看到更多代码并实际构建此应用程序时,它自然会更有意义。

因此,请在此处 [15] 在 QuickNode 注册一个帐户。

然后查看我下面的视频,了解如何获取测试网的 API 密钥:

测试网

我们暂时不会部署到“以太坊主网”。 为什么? 因为它要花真钱,所以不值得搞砸! 我们现在还在学习,我们将从一个测试网开始,它是主网的一个克隆,但它使用测试币,所以我们可以测试尽可能多的内容。 然而,重要的是要知道测试网是由真正的矿工运行并模仿“以太坊主网”世界的场景。

这很棒,因为我们可以在实际场景中测试我们的 dapp:

1.广播我们的交易

2.等待真正的矿工发现

3.等待挖出

4.等待它被广播回区块链告诉所有其他矿工更新他们的副本

获得一些测试币

以太坊有很多测试网,我们将使用由以太坊基金会运行的“Goerli”测试网。

为了部署到Goerli,我们需要使用GoerliETH。 为什么? 因为如果要部署到以太坊主网,就需要使用主网ETH! 因此,测试网克隆了主网的工作方式,唯一的区别是不涉及真钱。

为了获得 ETH 进行测试,我们必须向网络询问一些。 该测试ETH仅适用于该特定测试网,您可以通过水龙头为Goerli获取一些测试ETH。 您只需要找到一个可以使用的水龙头即可。

对于 MyCrypto,您需要连接您的钱包,注册一个帐户,然后再次单击相同的链接以请求资金。 歌尔力官方水龙头,需要登录Alchemy账号,即可获得2倍金额。

您可以从以下选择水龙头 URL:

网站

网址

数量

时限

我的密码

[16]

0.01

没有任何

官方歌尔力

[17]

0.25

24小时

链环

[18]

0.1

没有任何

设置 deploy.js 文件

将 deploy.js 与 run.js 分开是一种很好的做法。 run.js 是我们经常搞砸的地方,我们希望将它们分开。 在脚本文件夹下创建一个名为 deploy.js 的文件。 将所有内容从 run.js 复制到 deploy.js。 现在它们的内容完全一样,但是,我添加了一些 console.log 语句。

const main = async () => {
  const nftContractFactory = await hre.ethers.getContractFactory('MyEpicNFT');
  const nftContract = await nftContractFactory.deploy();
  await nftContract.deployed();
  console.log("Contract deployed to:", nftContract.address);

  // Call the function.
  let txn = await nftContract.makeAnEpicNFT()
  // Wait for it to be mined.
  await txn.wait()
  console.log("Minted NFT #1")

  txn = await nftContract.makeAnEpicNFT()
  // Wait for it to be mined.
  await txn.wait()
  console.log("Minted NFT #2")
};

const runMain = async () => {
  try {
    await main();
    process.exit(0);
  } catch (error) {
    console.log(error);
    process.exit(1);
  }
};

runMain();

部署到歌尔力测试网

我们需要修改 hardhat.config.js 文件,您可以在智能合约项目的根目录中找到该文件。

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

module.exports = {
  solidity'0.8.17',
  networks: {
    goerli: {
      url: process.env.QUICKNODE_API_KEY_URL,
      accounts: [process.env.GOERLI_PRIVATE_KEY],
    },
  },
};

在这里,我们基本上是在配置我们的 hardhat.config.js 以安全地使用我们的 .env 变量,process.env.quicknode_api_key_url & process.env.GOERLI_PRIVATE_KEY。 您现在需要打开一个终端并输入:

npm install dotenv

这基本上只是安装了允许我们使用环境变量的 dotenv 包。

现在您可以在项目的根目录中创建一个 .env 文件。 可以肯定的是,它应该匹配包含 hardhat.config.js 文件的路径。

您可以从 QuickNode 仪表板获取 API URL 并粘贴它。 然后,您需要您的私钥(不是您的公共地址!),您可以从 Meatmask [19] 获得并将其粘贴到位。

打开 .env 文件并粘贴我们从 quicknode 获得的链接,如下所示。

QUICKNODE_API_KEY_URL=
GOERLI_PRIVATE_KEY=

添加您的 API URL 和您的私钥后不要忘记删除。

注意:不要将此文件提交到 GITHUB。 它包含你的私钥,你可能会被黑客抢走,这个私钥和你的主网私钥是一样的。

打开你的 .gitignore 文件并在里面添加一个 .env 行。 (如果之前没有这行代码)

您的 .gitignore 文件应该如下所示。

node_modules
.env
coverage
coverage.json
typechain

#Hardhat files
cache
artifacts

为什么需要使用私钥? 因为为了执行像部署合同这样的交易,您需要登录区块链并签署/部署合同。 另外,你的用户名是你的公共地址,你的密码是你的私钥,这有点像登录 AWS 或 GCP 进行部署。

配置完成后,我们可以使用之前编写的部署脚本进行部署。

从 epic-nfts 的根目录运行此命令:

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

部署通常需要 20-40 秒。 我们不只是部署,我们还在 deploy.js 中创建 NFT,所以这也需要一些时间。 我们实际上需要等待交易被矿工挖出。 非常神奇,这个命令可以完成所有工作!

当我运行命令时,输出结果如下(当然你的合约地址应该不同):

以太坊创建时间_以太坊创建合约的过程_以太坊区块生成时间

我们可以使用Goerli Etherscan[20]查看合约地址,确保其处于正常状态!

习惯使用 Etherscan,因为这是跟踪部署是否出错的最简单方法。 如果 Etherscan 没有出现,那意味着它要么仍在处理中,要么出了什么问题!

如果它有效——太好了,你刚刚部署了一个合约! 是的。

在 OpenSea 上查看

信不信由你。 您刚刚创建的 NFT 将出现在 OpenSea 的 TestNet 站点上。

1.前往[21]

2.创建这个url:替换你的合约地址/TOKEN_ID[22]

例如,这是我的 Spongebob NFT 链接:[23],我的 tokenId 是'0',因为它是这个合约铸造的第一个 NFT。

基本上,如果您在几分钟内没有在 OpenSea 上看到您的 NFT,请刷新页面并再等待 15 分钟

以太坊区块生成时间_以太坊创建时间_以太坊创建合约的过程

所以在这里,你点击收藏下的 SquareNFT,你会看到你铸造的 NFT!

以太坊创建合约的过程_以太坊创建时间_以太坊区块生成时间

太棒了,我们已经创建了自己的 NFT 合约并铸造了两个 NFT。 虽然这是史诗般的,但它“有点蹩脚”,对吧? 每次都是同一张海绵宝宝照片! 我们如何在这里添加一些随机性并快速生成内容? 这就是我们接下来要讨论的内容 :) 。

代码

这里 [24] 是迄今为止所有代码的链接。

原文链接:

以太坊创建时间_以太坊区块生成时间_以太坊创建合约的过程

引用链接

[1] Solidity 扩展:

[2] 这里:

[3] 安全帽文档:

[4] 这里:

[5] 这里:

[6] 这里:

[7] Solidity 提供:#block-and-transaction-properties?utm_source=buildspace.so&utm_medium=buildspace_project

[8] OpenSea 要求:

[9]开海:

[10] 这个:

[11]:

[12] 这里:#ERC721-_exists-uint256-?utm_source=buildspace.so&utm_medium=buildspace_project

[13]开海:

[14] 快节点:

[15] 这里:

[16]:

[17]:

[18]:

[19] 肉面具:

[20] 歌尔力以太扫描:

[21]:

[22] 替换你的合约地址/TOKEN_ID:

[23]:

[24] 这里: