1.什么是IPFS?
IPFS是一种点对点分布式文件系统,主要用于无法存储在区块链上的数据。与更标准的文件共享协议 HTTP 不同,IPFS 具有特殊的属性,使其成为与区块链协同工作的去中心化数据模型的理想选择。主要的特点有:
1.分布式 - IPFS 由多个 IPFS 节点组成,因此没有一个实体可以控制网络上的共享内容。
2.不变性 - IPFS 上共享的内容不能更改或篡改。
3.可寻址性 - IPFS 上共享的内容使用唯一地址来定位网络上的内容。
4.可移植性 - 固定在 IPFS 上的数据可以重新固定或转移到其他节点上,从而帮助有价值的内容在网络上持续存在。
5.垃圾回收 - IPFS 处理数据的方式是,任何未被节点固定的内容最终都会从网络上消失,从而使网络远离不需要的数据和杂乱无章的内容
2.为什么要用IPFS来存储数据
区块链可以保存交易的长期账簿以及谁发送或签署了这些交易,但区块链在存储数据方面表现却很差。由于在区块链上存储数据时需要支付gas费,因此较大的数据量会导致天价gas。截至 2023 年,在以太坊上存储 1GB 的数据将花费约两亿五千万美元!这对 NFT 来说是相当大的麻烦。NFT 或区块链上使用的任何东西,通常都有一个链上的token,它有一个指向链下数据的指针(称为token URI)。该指针通常是一个指向 JSON 格式元数据文件的链接,其中包含 NFT 名称、描述等信息,通常还有一个指向链外图片的链接。在早期的 NFT 时代,这些指针或token URI 都是集中式服务器,这就造成了一个问题。没有什么能阻止服务器所有者将数据改成完全不同的内容,如果是这样的话,在区块链上购买一件艺术品的意义何在?这就是 IPFS 的优势所在,以及它在加密和分布式方面的特殊能力。只要文件存储在 IPFS 上,它就会获得一个基于文件内容的唯一 CID。如果文件只改变了一个像素或字符,那么它将获得一个完全不同的 CID。由于 IPFS 的加密性质,在 IPFS 上共享的任何内容都是不可更改的。
3.上传文件到IPFS
这里用到了Pinata工具将文件上传到IPFS中,Pinata主要是帮助构建者和创作者通过 IPFS 访问 NFT 和 Web3 基础设施,并通过专用网关使 IPFS 快速运行,API简单高效,适合初学者使用。
3.1 注册并登录Pinata
Pinata | Effortless IPFS File Management
右侧upload可以在ui界面将文件上传到ipfs中,今天主要讲调用api接口的实现
3.2 获取API key
进入apikey界面,点击右上角new key可以创建自己项目的apikey,他会给你jwt和apikey,记得一定要将给你的数据进行复制和保存,因为这些数据只能在生成的时候看一次。
3.3 向服务器发起post请求(js实现)
需要安装form-data和axios依赖,请求中的JWT为你自己获取到的JWT。
const uploadToIPFS = async(file)=>{
//创建表单数据对象
const formData = new FormData()
formData.append('file', file) //将文件以key:value的格式上传到表单中
//将文件的元数据转化为JSON格式存储到表单中(例如图片的名称和描述)
const pinataMetadata = JSON.stringify({
name: 'picture name',
});
formData.append('pinataMetadata', pinataMetadata);
//将配置项存储到表单中,cidversion表示使用cidv0还是v1
const pinataOptions = JSON.stringify({
cidVersion: 0,
})
formData.append('pinataOptions', pinataOptions);
try{
const res = await axios.post("https://api.pinata.cloud/pinning/pinFileToIPFS", formData, {
maxBodyLength: "Infinity",
headers: {
'Content-Type': `multipart/form-data; boundary=${formData._boundary}`,
'Authorization': `Bearer ${JWT}` //JWT为创建api key时给你的token
}
});
//返回图片在ipfs中的文件地址。res.data.IpfsHash为文件的cid
return `https://violet-adjacent-dingo-218.mypinata.cloud/ipfs/${res.data.IpfsHash}`
} catch (error) {
console.log(error);
}
}
4.上传NFT元数据到IPFS
//创建NFT
const createNFT = async(NFTName,description,price,fileUrl,router)=>{
//如果数据不全则报错
if(!NFTName || !description || !price || !fileUrl) return console.log('data is missing')
//将NFT数据转化成JSON格式存储到变量中
const data = JSON.stringify({
pinataContent: {
name: NFTName, //NFT名称
description, //NFT描述
external_url: "https://pinata.cloud", //NFT外部url
image: fileUrl //NFT图像
},
pinataMetadata: {
name: "nft.json" //NFT的存储名称
}
})
try {
//生成NFT的存储地址
const res = await axios.post("https://api.pinata.cloud/pinning/pinJSONToIPFS", data, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${JWT}`
}
});
const url = `https://violet-adjacent-dingo-218.mypinata.cloud/ipfs/${res.data.IpfsHash}`
console.log(url)
//触发创建交易的方法并传入NFT的存储地址和价格
await createSale(url,price,false)
} catch (error) {
console.log(error)
}
}
5.测试
最后一条返回的url就是所创建的NFT的元数据在ipfs上的存储地址