运用 Open Zeppelin、Truffle 和 Pinata。

ERC-721 规范[4]催生了以太坊上的非可替代代币(NFT)市场。ERC-721 是一个创立 NFT(表明绝无仅有事物)的规范。任何共同的事物都能够成为 NFT。一栋房子、一张棒球卡、一件艺术品等。但其包含的能量不仅仅在于事物是共同的、数字化的,更在于其可验证性。这就是 ERC-721 规范的闪光点。

创立 ERC-721 代币的主要问题来自于存储标的财物(译者注:NFT 背面代表的事物,或许是一张图片或一段文字或视频)。区块链并不适合存储很多数据。2017 年,Interplanetary 数据库的 Jamila Omar 估计,在以太坊上存储 1GB 数据的本钱将超过 400 万美元。

在以太坊上存储数据的本钱约为 17,500 ETH/GB,按今日的价格核算,约为 4,672,500 美元。-- Jamila Omar,2017[5]

已然存储 NFT 绑定的标的财物的本钱太高,以致无法运用区块链让存储,那么有什么替代计划呢?咱们能够运用传统的云存储来存储标的财物,如亚马逊的 S3 和微软的 Azure 供给了廉价的存储处理计划。但是,咱们所熟知的传统云存储有一个很大的缺点:他们不是暗码学上能够验证的

可验证性

NFT 的全部含义或许是对标的财物或数字财物可验证和可操控。

假如咱们不能以相似于验证代表财物的代币所有权的方式来验证标的财物自身,咱们就失去了最终目标。

处理这两个问题的办法是IPFS[6]。IPFS 是一个分布式存储网络。它的工作方式与云存储相似。你恳求内容,就会被回来该内容。但是,最大的不同是,内容的存储运用了全球的存储供给者网络。IPFS 运用了一种叫做内容可寻址的工具。这意味着,你不需求向俄亥俄州的数据中心提出恳求,而是对内容自身提出恳求。它或许坐落俄亥俄州(或许方位比较近)。有了内容可寻址性,你不再需求依靠单一的方位来检索内容。这关于全球区块链应用来说,分布式存储功率更高。

IPFS 还为咱们处理了可验证性问题。由于所有的内容都是根据内容自身来界说和存储的,假如一个内容被篡改或改动,咱们在企图验证内容时,就会出现不匹配的情况,知道内容是过错的。咱们用一个简略的比如来阐明一下。

Alice 在 IPFS 上存储了一张猫的图片,该猫的图片由一个内容标识符来表明。为简略起见,咱们假定标识符为 C

鲍勃恳求那张猫的照片,然后给那只可怜的猫画上胡子。当 Bob 上传他的图片时,他将不再具有相同的标识符。由于他改动了底层数据(从猫到胡子猫),所以 Bob 的标识符或许是M

假如鲍勃想把他的照片假充爱丽丝的照片任何人都会知道他在撒谎。爱丽丝的标识符与鲍勃的标识符不一致,因而,鲍勃企图假充爱丽丝的图像是能够验证的假象。

这有一个是视频介绍:https://youtu.be/6b8OANmw2kM

我想你能够看到,用 IPFS 来验证 NFTs 等数字财物,将是很便利的。就是考虑到这一点,让咱们看看如安在 IPFS 上创立一个 NFT 并存储相关的标的财物。

入门

关于本教程,你需求准备:

  • 一个文本修改器

  • 装置 IPFS(装置阐明[7]

  • Ganache -- 以太坊本地区块链(装置[8])。

  • 装置 Truffle (装置[9]

  • 装置 NodeJS 装置[10]

  • Pinata API 密钥, 要保证你创立 NFT 的珍贵财物被永久地存储在 IPFS 上。能够运转自己的 IPFS 节点[11]或运用 IPFS Pinning 服务[12]来完结。为了简略起见,咱们将经过 Pinata pinning 服务来进行,在此注册账户[13]

编写智能合约

在这儿先免责声明一下,作者不是一个专业的智能合约开发者。我知道足够风险,在区块链国际里,风险或许等于赔钱。所以要小心,要做研究,一定要找到最佳实践。本攻略的意图是作为一个入门引导,或许有更好的办法来完结我在这儿向你展示的内容。

ERC-721 代币由智能合约办理,幸运的是,OpenZeppelin[14]让你写好合约变得简略。咱们将运用 OpenZeppelin 的 ERC-721 合约来协助咱们开端。

首要,在终端,创立一个新的项目文件夹:

mkdir mySpecialAsset && cd mySpecialAsset

接下来,咱们将运用 NPM 初始化项目目录。

npm init -y

现在,能够运用 Truffle 来初始化智能合约。

truffle init

现在,咱们需求获得OpenZeppelin[15]合约。为此,像这样装置 Open Zeppelin 的 solidity 库:

npm install @openzeppelin/contracts

咱们需求为 NFT 代币想一个好名字。我计划把它的叫做 UniqueAsset,由于咱们要保证 NFTs 必须与共同的标的财物相相关。你能够把你的合约称为任何你喜爱的东西:

touch contracts/UniqueAsset.sol

接着就能够开端编码:

pragma solidity ^0.6.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol"

contract UniqueAsset is ERC721https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
constructor() public ERC721("UniqueAsset", "UNA") https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg}
}

咱们需求指定 solidity 的版别(或兼容的版别)这儿运用的是^0.6.0,经过修改 truffle-config.js文件,保证 Truffle 运用正确的 Solidity 版别编译你的合约。

还需求从 Open Zeppelin 导入合约 ERC721 及 Counters ,Counters 用来协助咱们创立递加 id 的代币。

最终,在咱们合约的结构函数中,咱们界说了代币称号和符号。

咱们需求在合约中加入一些逻辑:

首要,让咱们想一想咱们要做什么。咱们要针对特定的财物发行 NFTs。咱们期望这些财物能够核查,就像咱们期望所有权能够核查一样。所以,这儿有几件事需求考虑。

  1. 咱们要将 NFT 与 IPFS 内容标识符(哈希)相关起来。

  2. 咱们永远不期望铸造(或创立)一个与另一个 NFT 映射到相同 IPFS 哈希的 NFT。

让咱们先在合约中界说变量,咱们将用这些变量来协助操控以上两点。在合约代码的结构函数上面,增加以下内容:

using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
mapping(string => uint8) hashes;

constructor() public ERC721("UniqueAsset", "UNA") https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg}
...

运用计数器来界说一个_tokenIds变量,以跟踪发行的所有代币。最终,创立一个映射来相关 IPFS 哈希与代币。这将有助于避免发行相同哈希值的代币。

你的合约现在应该是这样的:

pragma solidity ^0.6.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract UniqueAsset is ERC721 https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
mapping(string => uint8) hashes;

constructor() public ERC721("UniqueAsset", "UNA") https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg}
}

咱们需求在合约中增加一个办法,允许为特定的 IPFS 哈希铸造 NFT,假如该哈希还没有铸造代币的话。咱们将在结构函数的下面增加:

function awardItem(address recipient, string memory hash, string memory metadata)
public
returns (uint256)https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg

require(hashes[hash] != 1);
hashes[hash] = 1;
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, metadata);
return newItemId;

}

这儿面有很多内容,让咱们一行一行的过。awardItem 函数需求三个参数。一个名为 recipient的地址变量,一个名为 hash的字符串变量,一个名为 metadata的字符串变量。地址变量recipient是将收到 NFT 的人的钱包地址。hash的字符串变量是与正在创立 NFT 的内容相相关的 IPFS 哈希。而 metadata的字符串变量是指向财物的 JSON 元数据的链接。元数据或许包含财物称号、指向该财物的图片链接或其他任何你想要的内容。

然后,在界说了函数之后,要把它变成public。这只是意味着它能够从智能合约外部调用,别的咱们还界说函数的回来值为uint256类型。

在函数里面,运用 Solidity 内置的 require来自动拒绝合约的调用,假如哈希之前现已被用来铸造 NFT。检查hashes映射是否有匹配的整数为 1 的哈希值,假如有,那么这个哈希值现已被运用了。

假如哈希没有被运用,咱们将经过函数传递的哈希增加到哈希映射中,并将其值设为 1。

最终,咱们递加_tokenIds变量,并铸造代币,回来代币标识符。

快速总结一下,合约现在需求一个以太坊钱包地址和一个 IPFS 哈希。它会检查以保证哈希值没铸造过 NFT。假如一切正常,就会创立一个新的 NFT,来对应该 IPFS 哈希。

好了,咱们现已写好了合约。现在怎么办?

让咱们编译并部署它,现在要用之前装置的 Ganache。经过 ganache-cli或运用桌面客户端启动 Ganache。

在项目目录下,有一个 migrations的文件夹。需求创立一个新的搬迁文件来部署 UniqueAsset, 新搬迁文件为2-deploy-contract.js。在该文件中,增加以下内容:

var UniqueAsset = artifacts.require("UniqueAsset");

module.exports = function(deployer) https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
deployer.deploy(UniqueAsset);
};

完结并保存后,在终端中,在项目目录下,运转。

truffle compile

假定没有碰到任何过错,你的合约现已编译完结,现在能够部署了。简略的运转:

truffle migrate

假如出现过错,你或许需求手动设置 Ganache 运转的端口,和你的 truffle-config.js文件中 networks部分设置的开发网络端口一致。

假如一切顺利,你就部署好了 UniqueAsset 合约。再次提示你,我不是智能合约开发专家。

现在咱们现已处理好了智能合约,咱们需求把标的财物放到 IPFS 上,并保证在铸造与之相关的 NFT 时,IPFS 是可用的。

在 IPFS 中增加财物

咱们将运用 Pinata 将财物增加到 IPFS 中,并保证它保持被 pin。咱们还将把 JSON 元数据增加到 IPFS 中,这样咱们就能够把它传递给 NFT 代币合约。所以,登录你之前在 Pinata 上创立的账户。在右上方,点击账户下拉菜单,选择账户。在那里你将能够看到 API key, 你能够悬停检查 API secret。

复制 API key 及 API secret,由于咱们将在代码中运用它们来上传咱们的财物文件。

一旦你有了你的 API Key 和 Secret Key,就能够写一些代码来发布你的财物文件到 IPFS。假如你在做完智能合约工作后感觉很累,不要担心,由于这儿超级简略的。其实,假如你想彻底跳过代码,Pinata有一个便利的上传功用的 UI[16]

在你的代码修改器中,创立一个名为 uploadFile.js的新文件。能够在你创立智能合约的同一个目录中。在咱们写代码之前,最好先准备好你的财物文件。只要保证它保存在你运用的电脑上的某个当地。关于我来说,我要上传的是我儿子画的一幅画。

如何用IPFS构建ERC721 NFT

现在咱们现已准备好将要上传的标的财物,让咱们来编写代码。咱们需求两个依靠联系来使咱们更简略做到这一点。在你的终端中,在项意图根目录,运转以下内容:

npm i axios form-data

现在,在uploadFile.js文件中增加以下内容:

const pinataApiKey = "YOURAPIKEY";
const pinataSecretApiKey = "YOURSECRETKEY";
const axios = require("axios");
const fs = require("fs");
const FormData = require("form-data");const pinFileToIPFS = async () => https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;

let data = new FormData();

data.append("file", fs.createReadStream("./pathtoyourfile.png"));

const res = await axios.post(url, data, https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
maxContentLength: "Infinity",
headers: https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
"Content-Type": `multipart/form-data; boundary=$https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpgdata._boundary}`
pinata_api_key: pinataApiKey,
pinata_secret_api_key: pinataSecretApiKey,
},
});
console.log(res.data);
};

pinFileToIPFS();

上传成功后,你会得到这样的结果。

https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
IpfsHash: 'QmfAvnM89JrqvdhLymbU5sXoAukEJygSLk9cJMBPTyrmxo',
PinSize: 2936977,
Timestamp: '2020-12-03T21:07:13.876Z'
}

这个哈希值就是你的财物的可验证的表明,它指向你在 IPFS 网络上的财物。假如有人篡改了你的财物,改动了你的财物,哈希值就会不同。在经过咱们的智能合约铸造 NFTs 时,应该运用这个哈希值。任何供给公共网关的 IPFS 主机都能够为你显现财物内容。

Pinata 有一个网关,你能够在这儿[17]检查我方才上传的财物。

最终,咱们需求做的是创立一个 JSON 文件,代表咱们的财物及其元数据。这使得你或许想要列出你的财物的任何服务更简略显现恰当的元数据。让咱们创立一个简略的 JSON 文件,像这样。

https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg
"name":"My Kid's Art",
"hash": "QmfAvnM89JrqvdhLymbU5sXoAukEJygSLk9cJMBPTyrmxo",
"by": "Justin Huner"
}

你能够增加任何你喜爱的元数据,但重要的是要包含哈希值。这是对实际财物的参阅。现在,用运用 Pinata 上传财物文件的方式上传这个 JSON 文件。当你拿回元数据的 IPFS 哈希值时,要把它保存起来。在创立 NFT 代币时需求这个。

还记得,智能合约采纳的是元数据字符串吗?这个字符串将是元数据的 IPFS URL。你要这样结构:

ipfs://YOUR_METADATA_HASH

因而,总结一下,你将向咱们之前创立的智能合约函数中传递三个项目。

  • 收件人地址

  • 财物哈希

  • 元数据 URL

合并起来

NFT 是咱们处理各类产品所有权的重要改进。它们很简略转让,并简化了建立所有权和证明所有权的进程。不过,缺失的一环,一直是对详细标的物所有权的验证。

经过将财物保存到 IPFS,并将 IPFS 哈希值与财物的 NFT 相关起来,咱们能够将财物的可验证所有权扩展到验证标的财物自身的有效性。

Pinata[18]有助于简化这一进程,使 IPFS 上的财物存储变得简略。


本翻译由 Cell Network[19] 资助支撑。

来源:https://medium.com/pinata/how-to-build-erc-721-nfts-with-ipfs-e76a21d8f914

参阅资料

[1]

登链翻译计划: https://github.com/lbc-team/Pioneer

[2]

翻译小组: https://learnblockchain.cn/people/412

[3]

Tiny 熊: https://learnblockchain.cn/people/15

[4]

ERC-721规范: https://eips.ethereum.org/EIPS/eip-721

[5]

Jamila Omar,2017: https://medium.com/ipdb-blog/forever-isnt-free-the-cost-of-storage-on-a-blockchain-database-59003f63e01

[6]

IPFS: https://ipfs.io/

[7]

装置阐明: https://docs.ipfs.io/how-to/command-line-quick-start/

[8]

装置: https://www.trufflesuite.com/ganache

[9]

装置: https://learnblockchain.cn/docs/truffle/getting-started/installation.html

[10]

装置: https://nodejs.org/en/

[11]

运转自己的IPFS节点: https://medium.com/pinata/how-to-deploy-an-ipfs-node-on-digital-ocean-c59b9e83098e

[12]

Pinning服务: https://medium.com/pinata/what-is-an-ipfs-pinning-service-f6ed4cd7e475

[13]

在此注册账户: https://pinata.cloud/

[14]

OpenZeppelin: https://openzeppelin.com/

[15]

OpenZeppelin: https://openzeppelin.com/

[16]

有一个便利的上传功用的 UI: https://pinata.cloud/pinataupload

[17]

在这儿: https://gateway.pinata.cloud/ipfs/QmfAvnM89JrqvdhLymbU5sXoAukEJygSLk9cJMBPTyrmxo/

[18]

Pinata: https://pinata.cloud/

[19]

Cell Network: https://www.cellnetwork.io/?utm_souce=learnblockchain

视野开拓

蒲寿庚对泉州的崛起居功阙伟。在他的主导下,泉州与上百个国家形成了贸易关系,货物贸易十分繁忙,市舶司管理的海船数量一度有15000艘之多。他还在泉州至杭州之间,专门设置了“海上站赤”(即海驿)15站,每站备有海船5艘,水军200人,专门运送从泉州入口的番货及贡品。因商贸之繁荣,泉州商人名闻天下,元代学者吴澄记载,泉州是“富商巨贾之窟宅,号为天下最”。-《浩荡两千年》

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注