如何用 14 行代码制作 NFT

nft121212

如果您是对区块链开发感兴趣的开发人员,您应该对 NFT 或非同质代币有所了解。在本文中,我们将了解它们背后的工程,以便您开始构建自己的。

在项目结束时,您将拥有自己的以太坊钱包,其中包含一个新的 NFT。本教程适合初学者,不需要任何以太坊网络或智能合约的先验知识。

图像 46

什么是 NFT?

NFT 代表不可替代的代币。ethereum.org 的这句话很好地解释了这一点:

NFT 是我们可以用来表示独特物品所有权的代币。他们让我们对艺术品、收藏品甚至房地产等事物进行代币化。他们一次只能有一个官方所有者,并且受到以太坊区块链的保护——没有人可以修改所有权记录或复制/粘贴新的 NFT。

什么是 NFT 标准或 ERC-721?

ERC-721 是最常见的 NFT 标准。如果您的智能合约实现了某些标准化的 API 方法,则可以将其称为 ERC-721 非同质代币合约。

这些方法在EIP-721中指定。像 OpenZeppelin 等开源项目通过将最常见的 ERC 标准实现为可重用库来实现,从而简化了开发过程。

什么是铸造 NFT?

通过铸造 NFT,您可以在区块链上发布一个独特的代币。此代币是您的智能合约的一个实例。

每个代币都有一个唯一的 tokenURI,它在符合特定模式的 JSON 文件中包含您的资产的元数据。元数据是您存储有关 NFT 信息的地方,例如名称、图像、描述和其他属性。

“ERC721 元数据架构”的 JSON 文件示例如下所示:

{
    
    
	"attributes": [
		{
    
    
			"trait_type": "Shape",
			"value": "Circle"
		},
		{
    
    
			"trait_type": "Mood",
			"value": "Sad"
		}
	],
	"description": "A sad circle.",
	"image": "https://i.https://img.chengxuka.comur.com/Qkw9N0A.jpeg",
	"name": "Sad Circle"
}

如何存储 NFT 的元数据?

存储 NFT 元数据的主要方式有三种。

首先,您可以将信息存储在链上。换句话说,您可以扩展您的 ERC-721 并将元数据存储在区块链上,但是这可能会很昂贵。

第二种方法是使用IPFS

第三种方法是让您的 API 返回 JSON 文件。

通常首选第一种和第二种方法,因为您无法调整底层 JSON 文件。对于本项目的范围,我们将选择第三种方法。

有关在 IPFS 中使用 NFT 的优秀教程,请阅读Alchemy 团队的这篇文章

我们将建造什么

情绪形状

在本文中,我们将创建和铸造我们自己的 NFT。这对初学者友好,不需要任何以太坊网络或智能合约的先验知识。不过,对这些概念有很好的了解将有助于您了解幕后发生的事情。

在接下来的内容中,我们将构建一个功能齐全的 React Web 应用程序,您可以在其中展示和销售您的 NFT。

这个项目有意用易于理解的代码编写的,不适合生产使用。

先决条件

MetaMask

图像 32

我们需要一个以太坊地址来与我们的智能合约进行交互。我们将使用Metamask作为我们的钱包。这是一个免费的虚拟钱包,可以管理你的以太坊地址。我们将需要它来发送和接收交易(在此处阅读更多信息)。例如,铸造 NFT 是一项交易。

下载 Chrome 插件和移动应用程序。这两个我们都需要,因为 Chrome 扩展程序不会显示您的 NFT。

图像 34

为了便于开发,请将网络更改为“Ropsten 测试网络”。你将需要一些 Eth 来支付部署和铸造 NFT 的费用。前往Ropsten 以太坊水龙头并输入您的地址。您应该很快会在您的 Metamask 帐户中看到一些测试 Eth。

图像 35

Alchemy

要与以太坊网络交互,您需要连接到以太坊节点。

运行自己的节点并维护基础设施本身就是一个项目。幸运的是,有节点即服务提供商为您托管基础设施。有很多选择,例如 Infura、BlockDaemon 和 Moralis。我们将使用Alchemy作为我们的节点提供者。

前往他们的网站,创建一个帐户,选择以太坊作为您的网络并创建您的应用程序。选择 Ropsten 作为您的网络。

图像 36

在您的面板上,单击应用程序上的“ view details”,然后单击“view key”。将您的 http 密钥保存在某个地方,因为我们稍后会需要它。

图像 38

NodeJS/NPM

我们将在项目中使用 NodeJS。如果您没有安装它,请按照freeCodeCamp 的这个简单教程进行操作。

初始化项目

在您的终端中,运行以下命令为您的项目创建一个新目录:

mkdir nft-project
cd nft-project

现在,让我们在 nft-project/ 目录下,再创建一个目录 ethereum/, 并使用 Hardhat 对其进行初始化。Hardhat 是一种开发工具,可让您轻松部署和测试您的以太坊软件。

mkdir ethereum
cd ethereum
npm init

然后,运行这些命令来创建一个 Hardhat 项目:

npm install --save-dev hardhat
npx hardhat

你会看到这个提示:

888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

Welcome to Hardhat v2.0.8

? What do you want to do? …
  Create a sample project
❯ Create an empty hardhat.config.js
  Quit

选择创建一个空的 hardhat.config.js。这将生成一个空hardhat.config.js文件,我们稍后将对其进行更新。

对于 Web 应用程序,我们将使用Next.js来初始化一个功能齐全的 Web 应用程序。回到根目录nft-project/,并初始化一个名为 web 的目录,以及 Next.js 应用程序:

cd ..
mkdir web
cd web
npx create-next-app@latest

您的项目现在看起来像这样:

nft-project/
	ethereum/
	web/

我们准备好深入研究一些真正的编码。

如何定义我们的 .env 变量

还记得我们之前从测试项目中获取的 Alchemy 密钥吗?我们将使用它与我们的 Metamask 帐户的公钥和私钥一起与区块链交互。

运行以下命令,在您的 ethereum/ 目录中创建一个名为 .env 的文件,然后安装dotenv。我们稍后会使用它们。

cd ..
cd ethereum
touch .env
npm install dotenv --save

对于您的.env文件,输入您从 Alchemy 导出的密钥,然后按照这些说明获取 Metamask 的私钥。

这是您的 .env 文件:

DEV_API_URL = YOUR_ALCHEMY_KEY
PRIVATE_KEY = YOUR_METAMASK_PRIVATE_KEY
PUBLIC_KEY = YOUR_METAMASK_ADDRESS

NFT 的智能合约

转到该ethereum/文件夹并再创建两个目录:contracts 和 scripts。一个简单的hardhat项目包含这些文件夹。

  • contracts/包含合约的源文件
  • scripts/包含部署和铸造我们的 NFT 的脚本
mkdir contracts
mkdir scripts

然后,安装 OpenZeppelin。OpenZeppelin Contract是一个开源库,带有预先测试的可重用代码,使智能合约开发更容易。

npm install @openzeppelin/contracts

最后,我们将为 NFT 编写智能合约。回到您的 contracts 目录并创建一个名为EmotionalShapes.sol. 您可以随意命名您的 NFT。

这个 .sol 扩展是指 Solidity 语言,我们将使用它来编写我们的智能合约。我们将只使用 Solidity 编写 14 行代码,所以如果您以前没有见过它,请不要担心。

cd contracts
touch EmotionalShapes.sol

这是我们的智能合约:

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

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

contract EmotionalShapes is ERC721 {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;

    constructor() ERC721("EmotionalShapes", "ESS") {}

    function _baseURI() internal pure override returns (string memory) {
        return "YOUR_API_URL/api/erc721/";
    }

    function mint(address to)
        public returns (uint256)
    {
        require(_tokenIdCounter.current() < 3); 
        _tokenIdCounter.increment();
        _safeMint(to, _tokenIdCounter.current());

        return _tokenIdCounter.current();
    }
}

让我们通过代码并了解发生了什么。

  1. 在文件的顶部,我们指定了要导入的 OpenZeppelin 模块。我们需要 ERC721 合约,因为它是我们智能合约的“基础”。它已经实现了EIP-721中指定的所有方法,因此我们可以安全地使用它。
  2. 计数器对于为我们的 NFT 生成增量 ID 很有用。我们将变量命名为_tokenIdCounter
  3. 在构造函数中,我们用它的名称和符号初始化了我们的 ERC721。我选择了 EmotionalShapes 和 ESS。
  4. 我们通过返回我们自己的函数来覆盖默认的_baseURI函数。我们将在一秒钟内构建它。总而言之,它将作为“前缀”添加到我们所有的 tokenURI 中的 URL。在上面的示例中,我们 NFT 的元数据将保存在一个 JSON 文件中,位于YOUR_API_URL/api/erc721/1
  5. 我们实现了“mint”功能。该功能可让您在区块链上发布此智能合约的实例。我要求_tokenIdCounter变量小于 3,因为我只会创建 NFT 的三个实例。如果你想铸造更多,你可以删除它。
  6. 最后,在 mint 函数中,我们将_tokenIdCounter 变量加 1,所以我们的 id 将是 1,然后是 2,然后是 3。然后,我们调用 OpenZeppelin 提供的函数_safeMint来发布代币。

如何为 NFT 构建元数据

如前所述,存储 tokenURI 有三种主要方式。我们将构建一个简单的 API 端点,将 NFT 的信息解析为 JSON。

我们的 Next.js 项目为我们提供了一种开发 API 路由的便捷方式。转到web/ 目录,在文件夹中找到 api/ 目录,在pages/ 目录下,然后在 erc721/ 目录中创建我们的动态[id].js路由([在此处](https://www.freecodecamp.org/news/p/18513919-9e93-4ab3-9f52-2448aafa8835/develop API routes)阅读有关路由的更多信息):

// web/pages/api/erc721/[id].js

const metadata = {
    
    
  1: {
    
    
    attributes: [
      {
    
    
        trait_type: "Shape",
        value: "Circle",
      },
      {
    
    
        trait_type: "Mood",
        value: "Sad",
      },
    ],
    description: "A sad circle.",
    image: "https://i.https://img.chengxuka.comur.com/Qkw9N0A.jpeg",
    name: "Sad Circle",
  },
  2: {
    
    
    attributes: [
      {
    
    
        trait_type: "Shape",
        value: "Rectangle",
      },
      {
    
    
        trait_type: "Mood",
        value: "Angry",
      },
    ],
    description: "An angry rectangle.",
    image: "https://i.https://img.chengxuka.comur.com/SMneO6k.jpeg",
    name: "Angry Rectangle",
  },
  3: {
    
    
    attributes: [
      {
    
    
        trait_type: "Shape",
        value: "Triangle",
      },
      {
    
    
        trait_type: "Mood",
        value: "Bored",
      },
    ],
    description: "An bored triangle.",
    image: "https://i.https://img.chengxuka.comur.com/hMVRFoJ.jpeg",
    name: "Bored Triangle",
  },
};

export default function handler(req, res) {
    
    
  res.status(200).json(metadata[req.query.id] || {
    
    });
}

为了这个项目,我使代码尽可能容易理解。这绝对不适合生产(请不要为您的 NFT 使用 https://img.chengxuka.comur url)。确保为您打算铸造的所有 NFT 定义元数据。

现在,转到 web 目录,并使用以下命令启动 Next.js 应用程序:

npm run dev

您的应用程序应该在 localhost:3000 上运行。为确保我们的端点正常工作,请访问http://localhost:3000/api/erc721/1,它应该使用您的第一个 NFT 元数据的 JSON 对象进行解析。

如何为 NFT 公开元数据

由于您的应用程序在本地托管,因此其他应用程序无法访问它。使用像ngrok这样的工具,我们可以将本地主机暴露给可公开访问的 URL。

图像 39

  1. 访问ngrok.com并完成注册过程
  2. 解压下载的包
  3. 在您的终端中,确保您 cd 进入您解压缩 ngrok 包的文件夹
  4. 按面板上的说明运行
./ngrok authtoken YOUR_AUTH_TOKEN
  1. 然后,运行此命令创建一个隧道,连接托管在 localhost:3000 上的 Web 应用程序
./ngrok http 3000
  1. 差不多了!在您的终端上,您应该会看到如下内容:
ngrok by @inconshreveable                                                                            (Ctrl+C to quit)
                                                                                                                     
Session Status                online                                                                                 
Account                       YOUR_ACCOUNT (Plan: Free)                                                                       
Version                       2.3.40                                                                                 
Region                        United States (us)                                                                     
Web Interface                 http://127.0.0.1:4040                                                                  
Forwarding                    http://YOUR_NGROK_ADDRESS -> http://localhost:3000                             
Forwarding                    https://YOUR_NGROK_ADDRESS -> http://localhost:3000                             

转到到 YOUR_NGROK_ADDRESS/api/erc721/1 确保您的端点正常工作。

如何部署我们的 NFT

现在我们已经完成了所有的基础工作(oof),让我们回到我们的ethereum/文件夹,准备部署我们的 NFT。

更改 ethreum/contracts/YOUR_NFT_NAME.sol 文件中的_baseURI函数以返回您的 ngrok 地址。

// ethereum/conrtacts/EmotionalShapes.sol

contract EmotionalShapes is ERC721 {
...
	function _baseURI() internal pure override returns (string memory) {
		return "https://YOUR_NGROK_ADDRESS/api/erc721/";
	}
...
}

要部署我们的 NFT,我们首先需要使用 Hardhat 编译它。为了使这个过程更容易,我们将安装ethers.js

npm install @nomiclabs/hardhat-ethers --save-dev

让我们更新我们的 hardhat.config.js:

require("dotenv").config();
require("@nomiclabs/hardhat-ethers");

module.exports = {
    
    
  solidity: "0.8.0",
  defaultNetwork: "ropsten",
  networks: {
    
    
    hardhat: {
    
    },
    ropsten: {
    
    
      url: process.env.DEV_API_URL,
      accounts: [`0x${
      
      process.env.PRIVATE_KEY}`],
    },
  },
};

要了解有关 hardhat 配置文件的更多信息,请查看它们的文档。我们已经使用我们的 Alchemy URL 配置了 ropsten 网络,并为它提供了您的 MetaMask 帐户的私钥。

最后,运行:

npx hardhat compile

这让 hardhat 为每个编译的合约生成两个文件。我们应该会看到一个新创建的artifacts/文件夹,其中包含您在文件夹中编译的合约contracts/。要了解有关其工作原理的更多信息,请阅读Hardhat 团队的教程

现在,让我们编写一个脚本,最终将我们的 NFT 部署到测试网络。在您的scripts/文件夹中,创建一个名为deploy.js.

// ethereum/scripts/deploy.js

async function main() {
    
    
  const EmotionalShapes = await ethers.getContractFactory("EmotionalShapes");
  const emotionalShapes = await EmotionalShapes.deploy();

  console.log("EmotionalShapes deployed:", emotionalShapes.address);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    
    
    console.error(error);
    process.exit(1);
  });

这段代码的灵感来自 hardhat 部署教程

ethers.js 中的ContractFactory是用于部署新智能合约的抽象,因此EmotionalShapes这里是我们的代币合约实例的工厂。对 ContractFactory 调用 deploy() 将启动部署,并返回解析为 ContractPromise。这是为您的每个智能合约功能提供方法的对象。

如何查看区块链上的 NFT

运行部署脚本:

node ./scripts/deploy.js

您应该在终端中看到EmotionalShapes deployed: SOME_ADDRESS。这是您的智能合约在 ropsten 测试网络上部署的地址。

如果您前往https://ropsten.etherscan.io/address/SOME_ADDRESS,您应该会看到新部署的 NFT。

如何铸造你的 NFT

现在您已经部署了 NFT,是时候为自己铸造它了!在您的scripts/文件夹中创建一个名为 mint.js的新文件。我们将使用 ethers.js 来帮助我们。

首先添加ethers.js包:

npm install --save ethers

然后,编写mint.js文件:

require("dotenv").config();
const {
    
     ethers } = require("ethers");

const contract = require("../artifacts/contracts/EmotionalShapes.sol/EmotionalShapes.json");
const contractInterface = contract.abi;

// https://docs.ethers.io/v5/api/providers
const provider = ethers.getDefaultProvider("ropsten", {
    
    
  alchemy: process.env.DEV_API_URL,
});

// https://docs.ethers.io/v5/api/signer/#Wallet
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

//https://docs.ethers.io/v5/api/contract/contract
const emotionalShapes = new ethers.Contract(
  YOUR_NFT_ADDRESS,
  contractInterface,
  wallet
);

const main = () => {
    
    
  emotionalShapes
    .mint(process.env.PUBLIC_KEY)
    .then((transaction) => console.log(transaction))
    .catch((e) => console.log("something went wrong", e));
};

main();

我们首先获取合约的接口(ABI)。来自 ethereum.org:

应用程序二进制接口 (ABI) 是与以太坊生态系统中的合约进行交互的标准方式,既可以从区块链外部进行,也可以用于合约到合约的交互。

您的 ABI 定义了其他人如何与您的合同交互。然后,我们使用 Alchemy 创建了我们的提供程序(记住节点即服务)。最后,我们用我们的私钥初始化我们的钱包。

main()函数调用mint方法,我们刚刚部署的智能合约中的方法。这个 mint 方法只接受一个参数,to,表示token 的接收者。由于我们是为自己铸造,所以我们将我们的 Metamask 帐户的公共地址。

如果一切顺利,您应该会在终端中看到交易记录。获取hash 属性,然后去https://ropsten.etherscan.io/tx/YOUR_HASH。你应该在那里看到铸币交易!

如何在 Metamask 钱包中查看 NFT

您需要首先下载 Metamask 的移动版本。然后,登录您的帐户。

您应该会看到一个 NFT 选项卡以及一个添加 NFT 按钮。单击按钮并输入您的智能合约的地址以及您铸造的 id。如果您是按照教程进行操作,则应从 id 开始1

https://img.chengxuka.com_0376

最后

恭喜!你刚刚铸造了自己的 NFT。在项目的下一部分中,我们将构建前端 React 应用程序以与我们的合约进行交互。最终目标是构建一个功能齐全的网络应用程序,您可以出售自己的 NFT。

原文链接:https://www.freecodecamp.org/news/how-to-make-an-nft/

猜你喜欢

转载自blog.csdn.net/hanru723/article/details/125673403