这是一个由三部分组成的系列文章的第二部分,该系列文章主要介绍Flow区块链、NFT和IPFS。您可以在这里阅读第一部分:
区块链研究实验室 | 如何使用Flow和IPFS创建NFT
在本教程中,我们将构建一个简单的React应用程序,该应用程序与Flow智能合约对接,以进行身份验证并获取用户拥有的NFT。然后,我们将解析NFT的元数据,以获取NFT底层数字资产(在本例中为视频)的IPFS位置。快速提醒我们正在努力的NFT-我们正在构建的NFT。
设置
对于本教程,您需要运行Flow仿真器。如果您不记得如何开始,请查看上一篇文章。一定要注意,Flow仿真器是Flow区块链的内存表示形式。因此,如果在第一篇文章和这篇文章之间,您关闭了模拟器,则需要继续执行以下操作:
启动模拟器
部署项目
铸造您的NFT
在本系列的第1部分中将详细介绍每个步骤。
另外,您将需要在计算机上安装NodeJS。
和往常一样,您将需要一个文本编辑器。
设置反应和依赖
我将pinata-party在这些教程的第一部分中开始的父目录中创建我的React应用程序。但是,如果需要,您可以在一个全新的目录中创建您的React应用程序。
要创建我们的应用程序,请运行:
npx create-react-app pinata-party-frontend
完成所有安装后,您将拥有一个名为的新目录pinata-party-frontend。切换到该目录,我们将需要安装一些依赖项。
首先,根据此处有关Flow的文档,您需要安装Flow JS SDK。实际上,对于前端设置的第一部分,我们将仅遵循Flow文档。
让我们继续运行下方命令:
npm i @onflow/fcl @onflow/types
我们将一些值存储为应用程序的全局变量。我们将利用环境变量。作为回应,这意味着创建.env文件并设置键值对,其中键以前缀REACT_APP。如果您遵循Flow文档,则将其设置为与他们的测试网连接。为了本教程的缘故,我们将连接到Flow仿真器。因此,我们需要进行一些更改。在您的.env文件中添加以下内容:
REACT_APP_ACCESS_NODE=http://localhost:8080
REACT_APP_WALLET_DISCOVERY=https://fcl-discovery.onflow.org/testnet/authn
REACT_APP_CONTRACT_PROFILE=0xf8d6e0586b0a20c7
REACT_APP_ACCESS_NODE如上所示,将值替换为本地仿真器URL。将REACT_APP_CONTRACT_PROFILE值替换为部署项目时收到的地址。
现在我们已经有了,我们需要创建一个配置文件,该文件将用于与Flow JS SDK进行交互。在src名为的目录中创建一个文件config.js。添加以下内容:
import {config} from "@onflow/fcl"
config()
.put("accessNode.api", process.env.REACT_APP_ACCESS_NODE) .put("challenge.handshake", process.env.REACT_APP_WALLET_DISCOVERY) .put("0xProfile", process.env.REACT_APP_CONTRACT_PROFILE)
该配置文件仅帮助JS SDK与Flow区块链(在这种情况下为仿真器)一起使用。要使该文件在整个应用程序中可用,请打开该index.js文件并添加以下行:
import "./config"
现在,让我们进行一些身份验证。如果您不想的话,不需要强迫人们进行身份验证,但是对本教程的第三部分进行身份验证非常重要,因为它可以实现NFT资产的转移。
我们需要创建一个身份验证组件。在src目录中,创建一个名为的文件AuthCluster.js。在该文件内,添加以下内容:
import React, {useState, useEffect} from 'react'
import * as fcl from "@onflow/fcl"
const AuthCluster = () => {
const [user, setUser] = useState({loggedIn: null})
useEffect(() => fcl.currentUser().subscribe(setUser), [])
if (user.loggedIn) {
return (
<div>
<span>{user?.addr ?? "No Address"}</span>
<button className="btn-primary" onClick={fcl.unauthenticate}>Log Out</button>
</div>
)
} else {
return (
<div>
<button className="btn-primary" onClick={fcl.logIn}>Log In</button>
<button className="btn-secondary" onClick={fcl.signUp}>Sign Up</button>
</div>
)
}
}
export default AuthCluster
使用登录和注册按钮来利用Flow JS SDK连接到钱包发现提供程序的能力很简单。您可以注册一个帐户或使用现有帐户登录。太好了!
现在,我们需要将此组件添加到我们的应用程序中。现在让我们保持简单。将App.js文件替换为以下内容:
import './App.css';
import AuthCluster from './AuthCluster';
function App() {
return (
<div className="App">
<AuthCluster />
</div>
);
}
export default App;
如果立即启动该应用程序(npm start),您应该会看到一个带有登录名和注册按钮的页面。实际上,这两个按钮都可以使用。试试看。
好的,既然我们的React应用程序已经设置好并且我们的依赖项已经安装,那么让我们开始构建为帐户获取NFT并显示它们的功能。
从FLOW中获取NFT
为了显示第一篇文章中介绍的NFT,我们需要能够与Flow区块链进行通信。在本教程的情况下,我们需要能够与Flow仿真器进行通信。我们已经告诉我们的应用程序,当我们设置.env文件时,仿真器正在端口8080上运行。但是现在,我们如何使用JavaScript与Flow对话?
幸运的是,Flow在其JS SDK中内置了此功能。如果您还记得的话,我们之前编写了一个脚本,用于根据NFT的令牌ID查找NFT,并返回令牌的元数据。它看起来像这样:
import PinataPartyContract from 0xf8d6e0586b0a20c7
pub fun main() : {String : String} {
let nftOwner = getAccount(0xf8d6e0586b0a20c7)
// log("NFT Owner")
let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)
let receiverRef = capability.borrow()
?? panic("Could not borrow the receiver reference")
return receiverRef.getMetadata(id: 1)
}
现在,我们只需要能够将其转换为JavaScript调用即可。让我们创建一个新组件,该组件将允许我们获取数据并最终显示NFT数据。在src目录中,创建一个名为的文件TokenData.js。在该文件中,添加以下内容:
import React, { useState } from "react";
import * as fcl from "@onflow/fcl";
const TokenData = () => {
const [nftInfo, setNftInfo] = useState(null)
const fetchTokenData = async () => {
const encoded = await fcl
.send([
fcl.script`
import PinataPartyContract from 0xf8d6e0586b0a20c7
pub fun main() : {String : String} {
let nftOwner = getAccount(0xf8d6e0586b0a20c7)
let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)
let receiverRef = capability.borrow()
?? panic("Could not borrow the receiver reference")
return receiverRef.getMetadata(id: 1)
}
`
])
const decoded = await fcl.decode(encoded)
setNftInfo(decoded)
};
return (
<div className="token-data">
<div className="center">
<button className="btn-primary" onClick={fetchTokenData}>Fetch Token Data</button>
</div>
{
nftInfo &&
<div>
{
Object.keys(nftInfo).map(k => {
return (
<p>{k}: {nftInfo[k]}</p>
)
})
}
<button onClick={() => setNftInfo(null)} className="btn-secondary">Clear Token Info</button>
</div>
}
</div>
);
};
export default TokenData;
在此文件中,我们将创建一个具有用于获取令牌数据的按钮的组件。我们还创建了一个清除令牌数据的按钮。单击提取按钮后,它会调用我们创建的函数fetchTokenData。该函数使用Flow JS SDK来执行与在本教程的第一部分中从命令行执行的完全相同的脚本,但是在React中执行。我们获取执行结果,并将结果设置为状态变量nftInfo。如果存在该变量,我们将从屏幕上的NFT元数据和一个使我们清除数据的按钮中呈现键值对。
我还添加了一些CSS,以使事情看起来不那么简单。如果要添加相同的CSS,就在这里,而您所要做的就是替换App.css为:
.App {
display: flex;
flex-direction: column;
min-height: 500px;
justify-content: center;
align-items: center;
}
button {
padding: 10;
height: 30px;
min-width: 100px;
cursor: pointer;
}
.btn-primary {
border: none;
background: rgb(255, 224, 0);
color: #282828;
}
.btn-secondary {
border: none;
background: rgb(0, 190, 221);
color: #282828;
}
.center {
text-align: center;
}
.token-data {
margin-top: 100px;
}
现在,只需将新组件添加到组件App.js下方即可,如下所示AuthCluster:
import './App.css';
import AuthCluster from './AuthCluster';
import TokenData from './TokenData';
function App() {
return (
<div className="App">
<AuthCluster />
<TokenData />
</div>
);
}
export default App;
立即签出您的应用,然后尝试获取您的令牌数据。它看起来应该像这样:
这太酷了!我们正在查找指定帐户所拥有的NFT,然后从该令牌中获取元数据。我们正在屏幕上显示该元数据,但是我们知道该元数据中的一个值会解析为视频文件。让我们看看是否可以在屏幕上渲染出来?
从IPFS获取媒体
您已经注册了Pinata帐户,并通过Pinata上传界面将视频文件添加到IPFS。这意味着您已经能够从IPFS提取内容。在Pin Explorer中,当您单击哈希时,您将被带到Pinata IPFS网关,在那里您的IPFS内容将被解析并显示给您。为了本教程的缘故,我们将使内容更加通用,同时强调IPFS的优点。
也就是说,您不必从Pinata网关中获取内容。相反,我们将从公共Protocol Labs网关获取它。
让我们潜入。
回到TokenData.js文件中,让我们添加一种显示最终从IPFS检索到的视频文件的方法。更新您的文件,使其看起来像这样:
import React, { useState } from "react";
import * as fcl from "@onflow/fcl";
const TokenData = () => {
const [nftInfo, setNftInfo] = useState(null)
const fetchTokenData = async () => {
const encoded = await fcl
.send([
fcl.script`
import PinataPartyContract from 0xf8d6e0586b0a20c7
pub fun main() : {String : String} {
let nftOwner = getAccount(0xf8d6e0586b0a20c7)
let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)
let receiverRef = capability.borrow()
?? panic("Could not borrow the receiver reference")
return receiverRef.getMetadata(id: 1)
}
`
])
const decoded = await fcl.decode(encoded)
setNftInfo(decoded)
};
return (
<div className="token-data">
<div className="center">
<button className="btn-primary" onClick={fetchTokenData}>Fetch Token Data</button>
</div>
{
nftInfo &&
<div>
{
Object.keys(nftInfo).map(k => {
return (
<p>{k}: {nftInfo[k]}</p>
)
})
}
<div className="center video">
<video id="nft-video" canplaythrough controls width="85%">
<source src={`https://ipfs.io/ipfs/${nftInfo["uri"].split("://")[1]}`}
type="video/mp4" />
</video>
<div>
<button onClick={() => setNftInfo(null)} className="btn-secondary">Clear Token Info</button>
</div>
</div>
</div>
}
</div>
);
};
export default TokenData;
我们添加了一个video元素,其源指向IPFS上的文件。您会注意到,我们必须拆分该uri值才能获取IPFS哈希,以便可以从IPFS网关中获取内容。让我们谈论一下这个URI。
我们使用NFT创建的uri看起来像ipfs://Qm…。我们之所以创建它,是因为IPFS桌面客户端将允许您单击并打开默认情况下看起来类似的链接。另外,Brave浏览器支持粘贴看起来像这样的链接。我们认为,随着我们的发展,这种链接格式将得到越来越多的支持。
但是,在这种情况下,我们需要散列,以便可以从IPFS公共网关获取内容。完成后,链接将如下所示:
https://ipfs.io/ipfs/QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6
现在,如果您尝试在我们的应用程序中获取令牌数据,则应获得以下内容:
我们的NFT不再是区块链上的匿名令牌。这是真正的实时数字资产!您的视频可能会有所不同,但希望您在应用程序中看到的结果基本上是相同的体验。
总结
这是一个非常简单的应用程序,您可以做很多事情来使其更漂亮,更具交互性,甚至向其中添加更多Flow元素。Flow JS SDK功能强大,因此我建议您通读文档。
我们使用Flow成功地向我们的应用程序添加了身份验证,我们创建了一个接口以获取有关NFT的信息,并且我们创建了一种不仅显示原始元数据,而且还显示基础数字资产的方法。所有这一切都由Flow区块链和IPFS来保护。我们知道NFT由说自己拥有它的人拥有,并且我们知道显示的内容是有效的,因为哈希已编码到NFT中。
在本系列的最后一部分中,我们将专注于创建一个迷你市场,使我们能够转让NFT,敬请期待~!
作者:链三丰,来源:区块链研究实验室
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。