主页 > imtoken官方版 > 建立你自己的以太坊 NFT 收藏(二)
建立你自己的以太坊 NFT 收藏(二)
另外——从头开始编写 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] 这里: