在这篇文章里,笔者将展示如何在没有软件公共技术背景下制作 NFT。然后,我们将学习如何用 Brownie、 Python、和 Chainlink 制作无限制可自定义的 NFT。以及我们也会看到如何在 OpenSea 的 NFT 市场上部署和销售我们的创作。
如果你在找使用 Truffle、JavaScript 和有趣的中世纪人物的教程,可以看看如何《构造、部署、和出售你的NFT》 。
什么是 NFT?
NFTs (Non-Fungible Tokens,不可置换代币) 可以用一个词来总结:唯一性。这些是部署在区块链上的智能合约,代表着某种东西的唯一性。
ERC20 vs ERC721
NFT 是一种区块链代币标准,与 ERC20 相似,像 AAVE、SNX、和LINK (准确来说是 ERC677)。ERC20 是“可置换”代币,这意味着那些代币是可被替换的 (replaceable) 和可互相兑换 (interchangeable)。
例如,无论你使用的是哪种美元钞票,你的美元钞票都将价值 1 美元。美元钞票上的序列号可能不一样,但钞票间是可以互相兑换的,而且它们仍然价值1美元。
另一方面,NFT 是“不可置换的”,它们遵守的是它们自己的代币标准 ERC721。例如,蒙罗丽莎是“不可置换的”。即使有人可以制作一个副本,永远也只会有一幅蒙罗丽莎。如果蒙罗丽莎是在区块链上创造的,那么它就是个 NFT。
NFT 是做什么的?
NFT 给创作者、艺术家、游戏设计师和其他职业者提供价值,保存在链上的部署还能永久保存。
你总能知道是谁创作了 NFT、谁拥有了 NFT、NFT 的来源,等等,它们给这些创作者带来的价值比传统艺术更大。在传统艺术里,分辨赝品会有点难,但链上历史是很容追踪到的。
由于智能合约和 NFT 是100%可编程的,NFT 还可以添加内置的版税和其他功能。给艺术家补助一直是一个问题,因为情况经常是艺术家的作品广泛传播而人们不知道作品是谁的。
越来越多的艺术家和工程师正在跃跃欲试,参与到这个有巨大价值的领域,因为这最终是让艺术家获得作品报酬的好途径。不止于此,NFT 是展示你的创造力以及在数字世界成为收藏者的有趣方式。
NFT 的价值
NFT 已经走了很长一段路了,并且我们不断看到有拍卖价格破纪录的 NFT,比如“Everyday:The First 5,000 Days” 以 6930 万美元售出。
因此,这里蕴含着很多价值,它也是在数字世界创作艺术和学习创建智能合约的有趣、动态、和很有魅力的方式。那么,现在我将教你如何制作 NFT 。
如何制作 NFT ?
文章不会涉及的内容
现在,制作 NFT 最简单的方法是到像 Opensea、 Rarible 或 Mintible 这些平台,跟着它们的逐步指引在它们平台部署。
你可以完全采用这个方法,但你可能会被绑定在平台上,受限于平台提供的功能。你不能实现无限制的自定义制作,或真正使用 NFT 的优势。但如果你是一个初级软件工程师,或没有非常丰富的技术知识,这是适合你的方法。
三星电子将于明年上半年推出能够交易和展示NFT的智能电视:金色财经报道,三星电子将于明年上半年推出能够交易和展示NFT的智能电视,计划内置美国NFT Gateway、法国La Collection、韩国Art Token等 3 家公司的NFT应用,此外也正在研究将虚拟资产(加密货币)等多种方式作为支付手段。(韩国经济日报)[2022/12/22 22:00:00]
如果你想成为一名很强的软件工程师,学习一些 solidity 的知识,且有能力可以用无限的创造力创造一些东西,请继续往下看吧!
如果你刚接触 solidity,不用担心,我们会从基础讲起。
如何用无限制的定制制作一个 NFT
我将用这个 ?NFT Brownie Mix 让你快速入门。这是一个工作代码库,有非常多样板代码。
准备要求
我们需要安装下列内容才能开始:
Nodejs 和 npm and npm
Metamask
如果你不熟悉 Metamask,你可以按着这个教程设置。
Rinkeby测试网上的ETH和LINK
我们还需要在 Rinkeby 以太坊测试网上工作,因此我们能免费把我们的合约部署到一个真正的区块链网络上。
测试网是用来测试我们的智能合约在现实世界运行得如何的好方法。我们需要有 Rinkeby 网络的 ETH和 LINK 测试币,我们可以在 Chainlink 文档中最新的水龙头链接里免费获得。
我们还需要添加 Rinkeby 的LINK测试币到我们的 metamask 里,我们可以跟着这个获取 LINK 文档的步骤。
如果你还是很疑惑,你可以跟着这个视频去做,只是要注意是用的 Rinkeby 而不是 Ropsten。
当在像 Ethereum 这样的智能合约平台上工作时,我们需要支付少量的 ETH,在需要从链下获取数据时,我们需要支付少量的 LINK。这就是为什么我们需要测试网的 LINK 和 ETH 测试币。
正式开始吧!这是我们准备部署到 OpenSea 的 NFT。
快速开始
git?clone?https://github.com/PatrickAlphaC/nft-mixcd?nft-mix现在我们需要安装ganache-cli和eth-brownie
pip?install?eth-brownienpm?install?-g?ganache-cli现在我们可以设置环境变量。如果你对环境变量不熟悉,你可以只把它们添加到你的.env文档,然后运行:
source?.env你刚刚克隆的代码库里应该有一个.env (环境)样本,它是加了环境变量注释的。取消注释就可以使用它们了!
你将需要一个WEB3_INFURA_PROJECT_ID(Web3 Infura 项目 ID) 和一个 PRIVATE_KEY(私钥)。注册一个免费 ?Infura 账号就会有这个 WEB3_INFURA_PROJECT_ID。它会使我们可以发送交易到区块链上。
NFT项目Porkers宣布完成600万美元融资:10月3日消息,NFT项目Porkers宣布完成600万美元融资,Bandai Namco、Bandai Gashapon JP、腾讯游戏的一群投资者和Web3爱好者等参投。本次融资所筹资金将主要用于在快照5/5的最后阶段进入奖金和流动资金池(目前为3/5)。[2022/10/3 18:38:24]
你还需要一个密钥,你可以在你的 Metamask 里获得。点一下那三个小点,然后点击Account Details(账户详情)和Export Private Key(导出私钥)。如果你准备把真钱放进去的话,不要把私钥告诉别人。
export?PRIVATE_KEY=YOUR_KEY_HEREexport?WEB3_INFURA_PROJECT_ID=YOUR_PROJECT_ID_HERE.env
现在我们可以用以下两个命令部署我们的 NFT 合约和创建我们第一件收藏品了。
brownie?run?scripts/simple_collectible/deploy_simple.py?--network?rinkebybrownie?run?scripts/simple_collectible/create_collectible.py?--network?rinkeby第一行命令用来把我们的 NFT 合约部署到 Rinkeby 区块链,第二行命令用来创建我们第一件收藏品。
你刚已经部署了我们第一份智能合约了!
它不做什么事,但不用担心。我将在这份教程的高级部分展示你可以如何把它部署到 OpenSea 上。但首先,让我们看看 ERC721 代币标准吧。
ERC721 代币标准
让我们在SimpleCollectible.sol文档里看看刚部署的合约吧。
//?SPDX-License-Identifier:?MITpragma?solidity?0.6.6;import?"????function?createCollectible(string?memory?tokenURI)?public?returns?(uint256)?{????????uint256?newItemId?=?tokenCounter;????????_safeMint(msg.sender,?newItemId);????????_setTokenURI(newItemId,?tokenURI);????????tokenCounter?=?tokenCounter?+?1;????????return?newItemId;????}}我们采用的是 OpenZepplin 的 ERC721 代币标准。我们导入的这个包 (package) 允许我们使用一个典型 ERC721 代币的全部功能。这定义了我们的代币将具有的所有功能,例如transfer意味着把我们的代币转移给新用户,safeMint表示创建新的代币,等等。
NFT市场Starly.io将推出NFT质押功能:4月1日消息,NFT Launchpad和市场Starly.io将推出NFT Staking功能。据悉,用户将可以质押Starly NFT。每张卡牌的质押奖励等于以STARLY代币表示的卡牌分数(Card Score),代币按照以下公式以线性方式分配:卡牌分数/365=24小时内分配的代币金额。简而言之,收集NFT卡牌中锁定的所有代币需要一年的时间。质押者每天最多只能领取一次代币,可以申领的代币金额取决于STARLY代币质押等级。
Starly.io表示,这一功能将在大约一个月的时间内实现,将涉及以前和未来Starly系列的所有卡牌。[2022/4/1 14:31:42]
在 OpenZepplin 的ERC721 代币合约里,你可以找到赋予我们合约的所有功能。我们的合约是通过这个命令行承继这些功能的:
contract?SimpleCollectible?is?ERC721?{solidity 的承继就是这样工作的。当我们部署合约时,constructor会被自动调用,它还需要一些参数。
constructor?()?public?ERC721?("Dogie",?"DOG"){????????tokenCounter?=?0;????}我们的构造函数也使用了ERC721的构造函数,我们只需要给它取一个名字和一个符号。在我们的例子中,是"Dogie"和"DOG"。这意味着每个我们创造的 NFT 都是 Dogie/DOG 类。
这就像每张 Pokemon 卡片都是一个 pokermon,或每个在集换式卡片上的棒球手都是一名棒球手。每个棒球手是独一无二的,但他们全部是棒球手。我们只是在用DOG类。
在顶部我们有tokenCounter,用来计数我们创建了多少这个类型的 NFT。每个新代币都会获得一个基于当前 tokenCounter 的 tokenId。
实际上,我们可以用 createCollectible 函数创建一个 NFT。这就是在我们的create_collectible.py脚本里调取的函数。
function?createCollectible(string?memory?tokenURI)?public?returns?(uint256)?{????????uint256?newItemId?=?tokenCounter;????????_safeMint(msg.sender,?newItemId);????????_setTokenURI(newItemId,?tokenURI);????????tokenCounter?=?tokenCounter?+?1;????????return?newItemId;????}_safeMint 函数创建新的 NFT,并把它分给任何调用了createdCollectible 的账户,即msg.sender,且会有一个从tokenCounter派生的 newItemId。这就是我们追踪谁拥有什么的方法——查看所有者的 tokenId。
你会发现我们还调用 _setTokenURI。
什么是 NFT 元数据和 TokenURI
当智能合约被创建了,NFT 就被创建了,人们很快会发现把大量数据部署到区块链真的超级超级贵。试想一下,储存1 KB 的数据可能就需要100万美元。
Invisible Friends#4672以110ETH价格成交,创下该NFT系列最高交易记录:2月28日消息,据 NFTGO.io 数据显示,NFT 项目隐形人Invisible Friends #4672 以 110 ETH 价格成交,约合 308,481.58 美元,创下该 NFT 系列最高交易记录。目前排名第二的是 Invisible Friends #2165,交易价格为 110 WETH,约合 302,332.89 美元;排名第三的是 Invisible Friends #2326,交易价格为 50 ETH,约合 138,690.60 美元。
此前 Invisible Friends 推出了一个慈善特别版 NFT Golden Friends,通过拍卖最终以 496.69 ETH 价格成交。[2022/2/28 12:20:23]
对于 NFT 来说,这显然是一个问题,因为拥有创意艺术意味着你必须把这个信息储存在某处。他们还想要一种轻量方法储存 NFT 的属性信息——这就是需要 tokenURI 和元数据的地方。
TokenURI
一个 NFT 上的 tokenURI是能展示这个代币的唯一标识符。一个 URI 可以是HTTPS上的 API 调用、一个 IPFS 的哈希、或任何其他代表唯一的东西。
它们遵循一套显示元数据的标准,如下:
{????"name":?"name",????"description":?"description",????"image":?"https://ipfs.io/ipfs/QmTgqnhFBMkfT9s8PHKcdXBn1f5bG3Q5hmBaR4U6hoTvb1?filename=Chainlink_Elf.png",????"attributes":?[????????{????????????"trait_type":?"trait",????????????"value":?100????????}????]}这些数据展现了一个 NFT 是什么样的以及它的属性。image部分指向另一个展示该 NFT 的 URI。这使得 NFT 可以更容易在像 Opensea、Rarible和 Mintable 这些 NFT 平台上部署,因为它们都需要这种元数据。
链下元数据 vs 链上元数据
现在你可能会想“等等,如果元数据不在链上,这是否意味着我的 NFT 可能会在某个时候消失了”?你的想法是对的。
如果你认为链下元数据意味着你无法用那元数据让你的智能合约互相交互,你的想法也是对的。
这也是为什么我们专注在链上元数据上,这样我们才可以对我们的 NFT 进行编程,使它们互相交互。
尽管如此,我们仍然需要image部分的链下元数据,因为我们还没有在链上储存大图像的好方法。但不要担心,通过使用 IPFS,我们还是可以免费在一个去中心化网络实现这一点。
这里是 IPFS 的一个 imageURI 示例,这个图像是按照《龙与地下城》教程创建的 Chainlink Elf。
The Chainlink Elf
我们没有给简单的 NFT 设一个 tokenURI 是因为我们只想展示一个基本示例。
SocialFi平台Torum将推出社交元宇宙和Avatar NFT:9月29日消息,SocialFi平台Torum宣布将推出社交元宇宙和第一个社交整合的Avatar NFT。Torum将基于币安智能链(BSC)发布21套Genesis Avatar NFT。每个Avatar代表Torum元宇宙中的一个唯一身份。这些BEP-1155 Avatar NFT由6种不同稀有度的Avatar碎片组合而成,这些碎片只能通过Torum Genesis盲盒NFT获得。有超过8500万个Avatar变体可供探索,让社区可以充分表达其内在创造力。由于Avatar NFT直接集成到Torum中,所有者可以将其Avatar用作社交化元宇宙头像,将“社交+NFT”概念的结合带入生活中。
每个盲盒包含一个Avatar NFT碎片,用于组装完整的Avatar NFT套件,只能使用XTM代币购买。在盲盒购买中花费的每一枚XTM将从代币供应量中永久销毁。随着XTM流通供应量的减少,它为健康的元宇宙经济中的各方创造双赢局面。从盲盒中解锁的Avatar NFT和NFT碎片也可以在Torum NFT市场上线和交易。(Bitcoin.com)[2021/9/29 17:14:45]
现在进入高级 NFT 部分,我们可以看到用链上元数据实现的一些很棒的功能,把 NFT 部署到 Opensea 上,把我们的 Dogie 放上去!
如果你想看我们刚讲过部分的重温视频,可以点击这里。
动态和高级的 NFT
动态 NFT 是那种随时间变化的,或具有我们可以用来互相交互的链上功能的 NFT。这些 NFT 给了我们无限制的自定义空间去制作整个游戏、构建世界、以及某种交互艺术。现在让我们进入高级部分吧。
高级部分快速开始
确认你的 metamask 里有足够的 ETH 和 LINK 测试币,然后运行下面的命令行:
brownie?run?scripts/advanced_collectible/deploy_advanced.py?--network?rinkebybrownie?run?scripts/advanced_collectible/create_collectible.py?--network?rinkeby我们这里的收藏品是从 Chainlink VRF (Virtual Routing and Forwarding,虚拟路由和转发) 返回的一个随机犬种。Chainlink VRF 能提供可验证随机数,也就我们 NFT 真正稀缺性来源。然后,我们就要创建它的元数据了。
brownie?run?scripts/advanced_collectible/create_metadata.py?--network?rinkeby然后,我们可以选择性地上载这个数据到 IPFS,这样我们就会获得一个 tokenURI。我在后面会展示给你看要怎么做。现在,我只需要用下面这个样本 tokenURI。
https://ipfs.io/ipfs/Qmd9MCGtdVz2miNumBHDbvj8bigSgTwnr4SbyH6DNnpWdt?filename=1-PUG.json如果你下载 IPFS Companion ?扩展程序到你的浏览器,你可以使用该 URL 来查看这个 URI 返回的是什么。它应该是下面展示的这样:
{????"name":?"PUG",????"description":?"An?adorable?PUG?pup!",????"image":?"https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png",????"attributes":?[????????{????????????"trait_type":?"cuteness",????????????"value":?100????????}????]}然后运行我们的 set_tokenuri.py 脚本:
brownie?run?scripts/advanced_collectible/set_tokenuri.py?--network?rinkeby我们得到的输出如下:
Running?'scripts/advanced_collectible/set_tokenuri.py::main'...Working?on?rinkebyTransaction?sent:?0x8a83a446c306d6255952880c0ca35fa420248a84ba7484c3798d8bbad421f88e??Gas?price:?1.0?gwei???Gas?limit:?44601???Nonce:?354??AdvancedCollectible.setTokenURI?confirmed?-?Block:?8331653???Gas?used:?40547?(90.91%)Awesome!?You?can?view?your?NFT?at?https://testnets.opensea.io/assets/0x679c5f9adC630663a6e63Fa27153B215fe021b34/0Please?give?up?to?20?minutes,?and?hit?the?"refresh?metadata"?button我们可以点击里面的链接看看它在 Opensea 上怎么样的。你可能需要点 refresh metadata ,等上几分钟。
随机犬种
现在说一下我们刚做了什么。这是我们的 AdvancedCollectible.sol:
pragma?solidity?0.6.6;import?"????//?add?other?things????mapping(bytes32?=>?address)?public?requestIdToSender;????mapping(bytes32?=>?string)?public?requestIdToTokenURI;????mapping(uint256?=>?Breed)?public?tokenIdToBreed;????mapping(bytes32?=>?uint256)?public?requestIdToTokenId;????event?requestedCollectible(bytes32?indexed?requestId);?????bytes32?internal?keyHash;????uint256?internal?fee;????uint256?public?randomResult;????constructor(address?_VRFCoordinator,?address?_LinkToken,?bytes32?_keyhash)????public?????VRFConsumerBase(_VRFCoordinator,?_LinkToken)????ERC721("Dogie",?"DOG")????{????????tokenCounter?=?0;????????keyHash?=?_keyhash;????????fee?=?0.1?*?10?**?18;????}????function?createCollectible(string?memory?tokenURI,?uint256?userProvidedSeed)?????????public?returns?(bytes32){????????????bytes32?requestId?=?requestRandomness(keyHash,?fee,?userProvidedSeed);????????????requestIdToSender[requestId]?=?msg.sender;????????????requestIdToTokenURI[requestId]?=?tokenURI;????????????emit?requestedCollectible(requestId);????}????function?fulfillRandomness(bytes32?requestId,?uint256?randomNumber)?internal?override?{????????address?dogOwner?=?requestIdToSender[requestId];????????string?memory?tokenURI?=?requestIdToTokenURI[requestId];????????uint256?newItemId?=?tokenCounter;????????_safeMint(dogOwner,?newItemId);????????_setTokenURI(newItemId,?tokenURI);????????Breed?breed?=?Breed(randomNumber?%?3);?????????tokenIdToBreed[newItemId]?=?breed;????????requestIdToTokenId[requestId]?=?newItemId;????????tokenCounter?=?tokenCounter?+?1;????}????function?setTokenURI(uint256?tokenId,?string?memory?_tokenURI)?public?{????????require(????????????_isApprovedOrOwner(_msgSender(),?tokenId),????????????"ERC721:?transfer?caller?is?not?owner?nor?approved"????????);????????_setTokenURI(tokenId,?_tokenURI);????}}我们使用 Chainlink VRF 从 PUG, SHIBA_INU, BRENARD列表里创建一个随机犬种。此时当我们调用 createCollectible 时,我们实际上在链下向 Chainlink VRF 节点发出了一个请求,然后返回一个随机数,以三个犬种里的一种来创建这个 NFT。
在你的 NFT 里使用一个真正的随机数是创造真正稀缺性的好方法,使用 Chainlink 预言机的随机数意味着你的数字具有可验证的随机性,无法被矿工修改。
你可以在 Chainlink VRF 文档里了解更多。
Chainlink 节点通过调用 fulfillRandomness函数来响应,并基于随机数创建收藏品。然后,我们还是必须调用 _setTokenURI 来给 NFT 提供所需的外观。
我们此时不设置我们 NFT 的属性,但属性对提升我们 NFT 的竞争力和交互性非常有用。你可以在龙与地下城的例子中看到设置了属性的 NFT 是怎样的。
来自 IPFS 的元数据
我们正在使用 IPFS 来存储两个文档:
1.?NFT 的图像 (八哥的形象)
2. tokenURI文档 (还包含了图像链接的 JSON 文档)
我们使用 IPFS 因为它是免费的去中心化平台。通过下载 IPFS 桌面版,点击 import按钮,我们可以把 tokenURI 和图像添加到 IPFS。
添加文档到 IPFS
然后,点击文档傍边的三个点,点 share link,然后复制提供的链接, 我们就可以分享 URI 了。然后,我们可以把这个链接添加到我们的 set_tokenuri.py 文档,把代 tokenURI 改为我们想要使用的。
坚持去中心化
但是,如果 tokenURI 只在我们自己的节点上,这意味着如果我们的节点离线了,其他人就看不到它了。因此,我们希望别人可以 pin (挂)我们的 NFT。我们可以使用像 Pinata 这样的服务商,即使我们的 IPFS 节点处于离线状态,他们也可以帮助我们保持数据在线上。
我想,以后会有越来越多的元数据储存在 IPFS 和去中心化储存平台。中心化服务器会式微,也就是说在上面的艺术品会永远消失。因此,请务必检查你的NFT使用的 tokenURI 的位置!
我预计以后会有越来越多人使用像 ?Filecoin 这样的去中心化储存平台,因为使用 pinning 服务并不非常去中心化。
继续前进
如果你想看一个高级 NFT 讲解视频,你可以看这个。
现在你已经有了制作好看、有趣、可自定义、具有交互性的 NFT,并把它部署到交易平台的技能了。
NFT 是能给艺术家的辛勤创作提供精确回报的一种有趣、强大的方式。祝你好运,享受这个过程吧!
郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。