• 译文出自:登链翻译计划 [1]

  • 译者:翻译小组 [2]

  • 校对:Tiny 熊 [3]

NFT 教程 - 如何展示 Flow 和 IPFS 上的 NFT 收藏品

本文是 NFT 教程的的第二部分,本教程主要介绍 Flow 区块链、NFT 和 IPFS。请先阅读第一部分 NFT 教程 - 用 Flow 和 IPFS 创建 NFT[4]。

在本文中,我们将构建一个简单的 React 应用程序,该应用程序与 Flow 智能合约交互,以验证和获取用户拥有的 NFT。然后,我们将解析 NFT 的元数据,以获得 NFT 的底层标的资产(在本例中为视频)的 IPFS 位置。提醒一下我们正在打造的 NFT,就像 NBA Top Shot 一样,只不过是不同的视频内容。

项目设置

本教程中,你需要运行 Flow 模拟器。如果你不记得如何启动,可以看看之前的文章或者查看 Flow CLI 文档。需要注意的是,Flow 模拟器是 Flow 区块链在内存的模拟。所以,如果关闭了模拟器,你需要继续做以下工作:

  • 启动 Flow 模拟器

  • 部署项目

  • 铸造你的 NFT

在本教程第一部分 NFT 教程 - 用 Flow 和 IPFS 创建 NFT[5] 详细介绍了其中的每一个步骤。

此外,还需要在你的机器上安装 NodeJS。你可以在这里安装 [6]。

和之前一样,你需要一个文本编辑器。

初始化 React 和安装依赖

在第一部分教程中创建的 pinata-party 项目目录下创建 React 应用(你也可以在一个全新的目录中创建你的 React 应用)。

要创建我们的应用程序,运行以下命令:

    npx create-react-app pinata-party-frontend  

当一切安装完成后,你会有一个新的目录,叫做 pinata-party-frontend , 切换到该目录,安装依赖。

首先,参考 Flow 文档 [7],需要安装 Flow JS SDK。前端的设置我们只需要按照 Flow 的文档进行即可:

    npm i @onflow/fcl @onflow/types  

一些值需要作为应用程序的全局变量来存储,这里使用环境变量。在 react 中,创建一个 .env 文件,并设置键值对,其中键值前缀为 REACT_APP 。在 Flow 的文档里,设置为与 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 交互。在 hide 目录下创建一个名为 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 资产的转移时,认证将是很重要的。

我们需要创建一个认证组件。在你的 hide 目录下,创建一个名为 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 (            <p>              <span>{user?.addr ?? "No Address"}span>              <button className="btn-primary" onClick={fcl.unauthenticate}>Log Outbutton>            p>          )        } else {          return (            <p>              <button className="btn-primary" onClick={fcl.logIn}>Log Inbutton>              <button className="btn-secondary" onClick={fcl.signUp}>Sign Upbutton>            p>          )        }      }      export default AuthCluster      //  rawAuthCluster.js  

代码很简单,使用一个登录和注册按钮,利用 Flow JS SDK 的能力连接到钱包提供者, 你可以注册一个账户或用现有账户登录。

现在需要把这个组件放到我们的应用程序中。我们先简单点吧。将你的 App.js 文件替换为以下内容。

    import './App.css';      import AuthCluster from './AuthCluster';function App() {        return (          <p className="App">            <AuthCluster />          p>        );      }      export default App;  

如果你现在启动应用程序 (npm start),你应该会看到一个有登录和注册按钮的页面。事实上,这两个按钮都是有功能的, 试试吧。

好了,现在 React 应用已经基本设置好了,让我们开始构建获取账户的 NFT 并显示它们。

从 Flow 中获取 NFT

为了显示我们在第一篇文章 [8] 中铸币的 NFT,需要与 Flow 区块链进行通信。现在是与 Flow 模拟器进行通信。设置 .env 文件时,已经告诉应用程序,模拟器是在 8080 端口上运行的。但现在,如何使用 JavaScript 与 Flow 交互?

幸运的是,Flow 在他们的 JS SDK 中内置了这个功能。如果你还记得,我们之前写了一个脚本,根据一个 NFT 的 token id 来查找它,并返回 token 的元数据。它看起来像这样:

    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)      }  

CheckTokenMetadata.cdc

现在,我们只需要将其转换为 JavaScript 调用即可。让我们创建一个新的组件,既能获取数据,又能最终显示 NFT 数据。在你的 hide 目录下,创建一个名为 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 (          <p className="token-data">            <p className="center">              <button className="btn-primary" onClick={fetchTokenData}>Fetch Token Databutton>            p>            {              nftInfo &&              <p>                {                  Object.keys(nftInfo).map(k => {                    return (                      <p>{k}: {nftInfo[k]}p>                    )                  })                }                <button onClick={() => setNftInfo(null)} className="btn-secondary">Clear Token Infobutton>              p>            }          p>        );      };      export default TokenData;      //rawTokenData.js  

在这个文件中,创建了一个组件,有一个按钮来获取代币数据。当点击获取按钮时,它会调用我们创建的一个名为 fetchTokenData 的函数。该函数使用 Flow JS SDK 来执行与在本教程第一部分中从命令行执行的脚本完全相同的脚本,但在 React 中。我们把执行的结果,设置到一个名为 nftInfo 的状态变量中。React 会根据 nftInfo 显示 NFT 元数据中的键值对。另外还有一个让清除数据的按钮。

我还加了一点 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 (          "App">        );      }export default App;  

运行应用程序并尝试获取代币数据,它应该是这样:

NFT 教程 - 如何展示 Flow 和 IPFS 上的 NFT 收藏品

这真是太酷了!我们正在查找指定的账户所拥有的 NFT,然后从该代币中获取元数据。并显示该元数据,我们知道该元数据中的一个值解析为一个视频文件。让我们把它显示出来。

从 IPFS 获取媒体文件

你已经注册了一个 Pinata[9] 账户,并通过 Pinata 上传界面将你的视频文件添加到 IPFS。这意味着你已经可以从 IPFS 中获取内容了。在 Pin Explorer[10] 中,当你点击一个哈希值时,你会被带到 Pinata IPFS 网关,在那里你的 IPFS 内容被解析并显示。为了教程更通用,我们还是从 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 (          <p className="token-data">            <p className="center">              <button className="btn-primary" onClick={fetchTokenData}>Fetch Token Databutton>            p>            {              nftInfo &&              <p>                {                  Object.keys(nftInfo).map(k => {                    return (                      <p>{k}: {nftInfo[k]}p>                    )                  })                }                <p className="center video">                  <video id="nft-video" canplaythrough controls width="85%">                    <source hide={`https://ipfs.io/ipfs/${nftInfo["uri"].split("://")[1]}`}                          type="video/mp4" />                  video>                  <p>                    <button onClick={() => setNftInfo(null)} className="btn-secondary">Clear Token Infobutton>                  p>                p>              p>            }          p>        );      };      export default TokenData;      //  rawTokenData.js  

我们已经添加了一个 video 标签,它指向 IPFS 上的文件。你会注意到,这里拆分了 uri 值,以获得 IPFS 哈希值,这样就可以从 IPFS 网关获取对应内容。先介绍下那个 URI。

我们用 NFT 创建的 uri 看起来像 ipfs://Qm... 。我们之所以这样创建,是因为 IPFS 桌面客户端默认允许你点击并打开这样的链接。另外,Brave 浏览器也支持粘贴这样的链接。并且我们认为这种链接形式会随着 IPFS 的发展得到越来越多的支持。

然而,在这里下,我们需要在利用哈希来从 IPFS 公共网关获取内容,并在页面上显示。因此链接会是这样:

https://ipfs.io/ipfs/QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6

现在,如果你访问我们的应用程序中获取代币数据,会看到如下界面:

NFT 教程 - 如何展示 Flow 和 IPFS 上的 NFT 收藏品

这是一个真正的活的数字资产 ! 你的视频可能会有所不同,但希望你在应用中感受到相同的体验。

最后

这是一个非常简单的应用,你可以做很多事情让它变得更漂亮,让它的交互性更强,甚至可以为它添加更多的 Flow 元素。Flow JS SDK 的功能很强大,所以我推荐大家阅读一下文档。

在第二部分成功地使用 Flow 为应用添加了身份验证,创建了一个接口来获取 NFT 的信息,创建了一种方法来显示了原始元数据以及对应的底层标的资产。这一切都由 Flow 区块链和 IPFS 来保障。我们知道 NFT 是由谁拥有,也知道显示的内容是有效性,因为哈希值被编码到 NFT 中。

在本教程的最后一篇,我们将专注于创建一个迷你交易市场,让我们转移 NFT。


本翻译由 Cell Network[11] 赞助支持。

来源: https://medium.com/pinata/how-to-display-your-nft-collection-like-nba-top-shot-with-flow-and-ipfs-6ba75048bf8a

参考资料

[1]

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

[2]

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

[3]

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

[4]

NFT 教程 - 用 Flow 和 IPFS 创建 NFT: https://learnblockchain.cn/article/2271

[5]

NFT 教程 - 用 Flow 和 IPFS 创建 NFT: https://learnblockchain.cn/article/2271

[6]

这里安装 : https://nodejs.org/en/

[7]

Flow 文档 : https://docs.onflow.org/flow-js-sdk/flow-app-quickstart

[8]

第一篇文章 : https://learnblockchain.cn/article/2271

[9]

Pinata: https://pinata.cloud/

[10]

Pin Explorer: https://pinata.cloud/pinexplorer

[11]

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