本文讲解如何从零到一打造自己的NFT

所有代码已上传至https://gitee.com/SJshenjian/blockchain/tree/master/hardhat-nft-fcc

1. 下载安装项目

git clone https://gitee.com/SJshenjian/blockchain.gitcd hardhat-nft-fccyarn

2. 配置修改

  • 新增订阅

在https://vrf.chain.link/中新增订阅,然后修改
helper-hardhat-config.js中的subscriptionId值为自己的

5: {        name: "goerli",        subscriptionId: "5115", // add your ID here!    },
  • 注册https://www.pinata.cloud/或https://nft.storage用于NFT上传

注册API_KEY修改.env中配置

NFT_STORAGE_KEY=XXXXXXPINATA_API_KEY=XXXXXXPINATA_API_SECRET=XXXXXX

3. 运行部署

我们运行本地部署yarn hardhat deploy发现一切正常

(base) PS D:\blockchain\blockchain\hardhat-nft-fcc> yarn hardhat deployyarn run v1.22.19warning package.json: No license field$ D:\blockchain\blockchain\hardhat-nft-fcc\node_modules\.bin\hardhat deployNothing to compileLocal network detected! Deploying mocks...deploying "VRFCoordinatorV2Mock" (tx: 0x1f95b6dc03b0f019875a16c4e529a7ce7c20897a493463c3aa4a80a5f053f1af)...: deployed at 0x5FbDB2315678afecb367f032d93F642f64180aa3 with 2543420 gasdeploying "MockV3Aggregator" (tx: 0x07b11cc60051bd9be3bba6b22675974999ac14b8fc841ae5bf19418b634b86cc)...: deployed at 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 with 569671 gasMocks Deployed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!You are deploying to a local network, you'll need a local network running to interactPlease run `yarn hardhat console --network localhost` to interact with the deployed smart contracts!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!----------------------------------------------------deploying "BasicNft" (tx: 0x3ea769ae9694432e56ec58ca884df6853fda5a1a0f4f89ecf3c2aecf24e747ac)...: deployed at 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 with 2014793 gas  ----------------------------------------------------deploying "DynamicSvgNft" (tx: 0x05659748cafee03724c05003a44e1712cc8cddba0dcb4e73d5de2732d2e52372)...: deployed at 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 with 4585544 gas----------------------------------------------------deploying "RandomIpfsNft" (tx: 0x69864f92b769bc30e7759fd5e3048bafaf7125ea146d3528c346d585628b0b16)...: deployed at 0x0165878A594ca255338adfa4d48449f69242Eb8F with 3575089 gasBasic NFT index 0 tokenURI: ipfs://bafybeig37ioir76s7mg5oobetncojcm3c3hxasyd4rvid4jqhy4gkaheg4/?filename=0-PUG.jsonDynamic SVG NFT index 0 tokenURI: data:application/json;base64,eyJuYW1lIjoiRHluYW1pYyBTVkcgTkZUIiwgImRlc2NyaXB0aW9uIjoiQW4gTkZUIHRoYXQgY2hhbmdlcyBiYXNlZCBvbiB0aGUgQ2hhaW5saW5rIEZlZWQiLCAiYXR0cmlidXRlcyI6IFt7InRyYWl0X3R5cGUiOiAiY29vbG5lc3MiLCAidmFsdWUiOiAxMDB9XSwgImltYWdlIjoiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQRDk0Yld3Z2RtVnljMmx2YmowaU1TNHdJaUJ6ZEdGdVpHRnNiMjVsUFNKdWJ5SS9QZ284YzNabklIZHBaSFJvUFNJeE1ESTBjSGdpSUdobGFXZG9kRDBpTVRBeU5IQjRJaUIyYVdWM1FtOTRQU0l3SURBZ01UQXlOQ0F4TURJMElpQjRiV3h1Y3owaWFIUjBjRG92TDNkM2R5NTNNeTV2Y21jdk1qQXdNQzl6ZG1jaVBnb2dJRHh3WVhSb0lHWnBiR3c5SWlNek16TWlJR1E5SWswMU1USWdOalJETWpZMExqWWdOalFnTmpRZ01qWTBMallnTmpRZ05URXljekl3TUM0MklEUTBPQ0EwTkRnZ05EUTRJRFEwT0MweU1EQXVOaUEwTkRndE5EUTRVemMxT1M0MElEWTBJRFV4TWlBMk5IcHRNQ0E0TWpCakxUSXdOUzQwSURBdE16Y3lMVEUyTmk0MkxUTTNNaTB6TnpKek1UWTJMall0TXpjeUlETTNNaTB6TnpJZ016Y3lJREUyTmk0MklETTNNaUF6TnpJdE1UWTJMallnTXpjeUxUTTNNaUF6TnpKNklpOCtDaUFnUEhCaGRHZ2dabWxzYkQwaUkwVTJSVFpGTmlJZ1pEMGlUVFV4TWlBeE5EQmpMVEl3TlM0MElEQXRNemN5SURFMk5pNDJMVE0zTWlBek56SnpNVFkyTGpZZ016Y3lJRE0zTWlBek56SWdNemN5TFRFMk5pNDJJRE0zTWkwek56SXRNVFkyTGpZdE16Y3lMVE0zTWkwek56SjZUVEk0T0NBME1qRmhORGd1TURFZ05EZ3VNREVnTUNBd0lERWdPVFlnTUNBME9DNHdNU0EwT0M0d01TQXdJREFnTVMwNU5pQXdlbTB6TnpZZ01qY3lhQzAwT0M0eFl5MDBMaklnTUMwM0xqZ3RNeTR5TFRndU1TMDNMalJETmpBMElEWXpOaTR4SURVMk1pNDFJRFU1TnlBMU1USWdOVGszY3kwNU1pNHhJRE01TGpFdE9UVXVPQ0E0T0M0Mll5MHVNeUEwTGpJdE15NDVJRGN1TkMwNExqRWdOeTQwU0RNMk1HRTRJRGdnTUNBd0lERXRPQzA0TGpSak5DNDBMVGcwTGpNZ056UXVOUzB4TlRFdU5pQXhOakF0TVRVeExqWnpNVFUxTGpZZ05qY3VNeUF4TmpBZ01UVXhMalpoT0NBNElEQWdNQ0F4TFRnZ09DNDBlbTB5TkMweU1qUmhORGd1TURFZ05EZ3VNREVnTUNBd0lERWdNQzA1TmlBME9DNHdNU0EwT0M0d01TQXdJREFnTVNBd0lEazJlaUl2UGdvZ0lEeHdZWFJvSUdacGJHdzlJaU16TXpNaUlHUTlJazB5T0RnZ05ESXhZVFE0SURRNElEQWdNU0F3SURrMklEQWdORGdnTkRnZ01DQXhJREF0T1RZZ01IcHRNakkwSURFeE1tTXRPRFV1TlNBd0xURTFOUzQySURZM0xqTXRNVFl3SURFMU1TNDJZVGdnT0NBd0lEQWdNQ0E0SURndU5HZzBPQzR4WXpRdU1pQXdJRGN1T0MwekxqSWdPQzR4TFRjdU5DQXpMamN0TkRrdU5TQTBOUzR6TFRnNExqWWdPVFV1T0MwNE9DNDJjemt5SURNNUxqRWdPVFV1T0NBNE9DNDJZeTR6SURRdU1pQXpMamtnTnk0MElEZ3VNU0EzTGpSSU5qWTBZVGdnT0NBd0lEQWdNQ0E0TFRndU5FTTJOamN1TmlBMk1EQXVNeUExT1RjdU5TQTFNek1nTlRFeUlEVXpNM3B0TVRJNExURXhNbUUwT0NBME9DQXdJREVnTUNBNU5pQXdJRFE0SURRNElEQWdNU0F3TFRrMklEQjZJaTgrQ2p3dmMzWm5QZ289In0=Random IPFS NFT index 0 tokenURI: ipfs://QmZYmH5iDbD6v3U2ixoVAjioSzvWJszDzYdbeCLquGSpVmDone in 10.52s.

4. IPFS介绍

IPFS是星际文件系统的简写,是去中心化存储龙头。我们NFT制作依赖于IPFS存储,最原始的文件如图片、视频都存储在IPFS中,一但上传不可更改。
首先我们访问https://github.com/ipfs/ipfs-desktop/releases下载对应版本客户端安装

在客户端文件中我们输入bafybeig37ioir76s7mg5oobetncojcm3c3hxasyd4rvid4jqhy4gkaheg4浏览后可以看到如下信息

{    "name": "PUG",    "description": "An adorable PUG pup!",    "image": "https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png",    "attributes": [        {            "trait_type": "cuteness",            "value": 100        }    ]}

这就是NFT中的TOKEN_URI:值是json文件,定义了metadata信息,其中image指定图片的去中心化存储位置,当我们浏览器访问https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png地址时,一个可爱的小狗图片就展现了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yV9XmZNH-1666522940517)(https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png)]

好了,到此为止我们总结下NFT图像制作具体步骤

  1. GET IPFS
  2. Add TokenURI json file to IPFS
  3. Add IPFS URI TO YOUR NFT URI
5. NFT基础
  • 在BasicNFT.sol中我们已经有了TokenURI json file, 只需要进行上述第三步骤即可
// SPDX-License-Identifier: MITpragma solidity ^0.8.8;import "@openzeppelin/contracts/token/ERC721/ERC721.sol";contract BasicNft is ERC721 {    string public constant TOKEN_URI =        "ipfs://bafybeig37ioir76s7mg5oobetncojcm3c3hxasyd4rvid4jqhy4gkaheg4/?filename=0-PUG.json";    uint256 private s_tokenCounter;    constructor() ERC721("Dogie", "DOG") {        s_tokenCounter = 0;    }    function mintNft() public {        s_tokenCounter = s_tokenCounter + 1;        _safeMint(msg.sender, s_tokenCounter);    }    function tokenURI(uint256 tokenId) public view override returns (string memory) {        // require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");        return TOKEN_URI;    }    function getTokenCounter() public view returns (uint256) {        return s_tokenCounter;    }}

其中ERC-721 为 NFT 引入了一个标准,换言之, 这种类型的代币是独一无二的,并且可能与来自同一智能合约的另一代币有不同的价值,也许是因为它的年份、稀有性、甚至是它的观感

  • 运行yarn hardhat deploy --network goerli --tags basicnft部署NFT图像至goerli测试网络,注意之前在alchemy申请的GOERLI_RPC_URL是否过期,如果不能访问重新申请
$ D:\blockchain\blockchain\hardhat-nft-fcc\node_modules\.bin\hardhat deploy --network goerli --tags basicnftNothing to compile----------------------------------------------------reusing "BasicNft" at 0xa14Bb4725c302c04888010C343dC660902D6B50CDone in 5.25s.

访问部署地址,NFT至此完成https://goerli.etherscan.io/address/0xa14Bb4725c302c04888010C343dC660902D6B50C

6.随机NFT

对于RandomIpfsNft.sol做的功能类似盲盒抽奖,用户充值然后抽取NFT,普通稀缺各占一定比例,这种去中心化的机制下,让商家没有作假的可能。完全透明

7. SVG上NFT

DynamicSvgNft.sol实现了SVG图片制作为NFT,自行查看吧

到此为止,区块链系列先告一段落了

欢迎关注公众号算法小生或沈健的技术博客shenjian.online