构建一个多链 NFT 分析应用程序
2025-05-29 18:24
登链社区
2025-05-29 18:24
订阅此专栏
收藏此文章
登链社区

概述

在不断发展的区块链和非同质化代币 (NFT) 世界中,访问和分析跨多个链的 NFT 数据的能力变得越来越有价值。本指南深入探讨了如何构建一个多链 NFT 分析应用程序,利用 带有缓存元数据的 NFT API 插件在 QuickNode Marketplace 上的高级功能。我们的目标是展示如何轻松创建一个强大的 NFT 分析应用程序,该应用程序可以在多链级别上运行,并实时提供 NFT 详细信息,例如 NFT 元数据、交易所数据、交易活动、历史价格、诈骗 / 垃圾邮件评分、稀有度和所有权信息。

你将学到什么

在本指南中,你将学习:

  • 使用 带有缓存元数据的 NFT API 插件
  • 构建一个支持 Ethereum、Polygon、Arbitrum、Optimism 和 BSC 的多链 NFT 分析应用程序。
  • 获取和显示 NFT 元数据、交易所数据、交易活动等。
  • 创建一个交互式且视觉上吸引人的前端,以展示各种区块链上的 NFT 集合。

你需要什么

在开始之前,请确保你具备以下条件:

  • JavaScript/TypeScript 和 React 的基本知识
  • 为 React 设置的开发环境(Node.js、npm 和代码编辑器)
  • 通过 QuickNode 帐户访问带有缓存元数据的 NFT API 插件

带有缓存元数据的 NFT API 插件

功能和特性

对于涉足 NFT 领域的开发者来说,带有缓存元数据的 NFT API 插件是一个强大的工具。它的功能包括:

  • 直接访问实时 NFT 元数据:实时检索有关 NFT 的详细信息,包括特征、稀有度和所有权。
  • 交易所数据和交易活动:访问来自各种市场的综合数据,包括历史价格和最近的交易。
  • 诈骗 / 垃圾邮件评分:使用诈骗和垃圾邮件评分评估 NFT 的合法性。
  • CDN 缓存资产:API 返回针对 Web 优化的 NFT 资产大小的 CDN 缓存 URL,非常适合应用程序开发。
  • 跨链支持:聚合 Ethereum、Polygon、Arbitrum、Optimism 和 BSC 上的 NFT 信息。

对开发者的价值

与手动提取和管理区块链数据的过程相比,使用带有缓存元数据的 NFT API 插件具有显着的优势:

方面
手动方法
使用 NFT API 插件
时间和资源
需要为每个区块链设置数据抓取过程、解析日志和管理数据库。
提供跨多个区块链聚合和索引的数据,无需单独的数据管理。
开发复杂性
涉及对区块链协议和数据规范化过程的深入理解。
通过抽象区块链数据提取和规范化的复杂性来简化开发。
用户体验
实时数据抓取的延迟可能会阻碍应用程序的响应能力和功能丰富性。
确保快速、可靠地访问优化数据,从而能够创建响应迅速且功能丰富的应用程序。

设置端点

使用 带有缓存元数据的 NFT API 设置端点非常容易。如果你尚未注册,可以在此处创建一个帐户。

登录后,导航到 quicknode.com/endpoints 页面,然后单击 创建端点。选择 Ethereum mainnet(** 或其他支持的网络** 之一),然后单击 下一步。然后,系统将提示你配置插件。激活 带有缓存元数据的 NFT API。之后,只需单击 创建端点

如果你已经有一个没有插件的端点,请转到端点内的 插件 页面,选择 带有缓存元数据的 NFT API,然后激活它。

准备好端点后,转到 插件 页面,然后复制你的 BlockSpan 的 API URL,该 URL 位于 带有缓存元数据的 NFT API 插件附近。

该 URL 应类似于以下内容。在下一节中,你将需要你的密钥 API 密钥。

https://api.blockspan.com/{YOUR_SECRET_TOKEN}/v1/

根据你要使用的区块链数量,你应该重复此过程。因此,每个链都会有不同的密钥 API 密钥。

image-20240930222847819.png

构建应用程序

要开始构建你的 NFT 分析应用程序,必须设置一个强大的开发环境。这将确保你在进行操作时的工作流程顺畅高效。

设置项目

安装 Node.js 和 npm

首先,请确保你已安装 Node.js 和 npm (Node Package Manager)。Node.js 是在浏览器外部运行 JavaScript 代码的运行时环境,而 npm 帮助管理你的项目将依赖的包。

  • 下载并安装 Node.js
  • npm 包含在 Node.js 中,因此安装 Node.js 将自动安装 npm。
安装 React 和其他依赖项

使用 Create React App 工具设置项目的基础:

npx create-react-app my-app --template typescript
cd my-app

此命令使用 TypeScript 设置一个新的 React 项目,它将静态类型添加到你的 JavaScript 代码,从而增强其可靠性和可维护性。

安装其他软件包,例如用于 API 请求的 Axios、React Social Icons 和用于样式的 Tailwind CSS:

npm install -D tailwindcss postcss autoprefixer
npm install axios react-social-icons
配置 Tailwind CSS

生成 Tailwind 配置文件。这将创建一个最小的 tailwind.config.js 文件,你可以在其中自定义 Tailwind 设置,以及一个 postcss.config.js 文件,用于 PostCSS 配置。

npx tailwindcss init -p

配置 tailwind.config.js 文件并添加所有模板文件的路径。

/** @type {import('tailwindcss').Config} */
module.exports = {
 content: ['./src/**/*.{js,jsx,ts,tsx}'],
 theme: {
  extend: {},
 },
 plugins: [],
}

通过将 src/index.css 的内容替换为以下指令以在 CSS 中配置 Tailwind,以包含 Tailwind 的基础、组件和实用程序样式。

@tailwind base;
@tailwind components;
@tailwind utilities;

它是自动导入的,但始终最好确保在 src/index.tsx 文件中导入 src/index.css,以在你的构建中包含 Tailwind CSS:

import './index.css'

构建项目

设计应用程序结构

拥有一个精心计划的应用程序结构对于开发效率和未来的可扩展性至关重要。对于本指南中构建的多链 NFT 分析应用程序,我们将构建诸如 ChainSelector 和 NFTCollectionCard 之类的组件,它们将充当我们应用程序的两个主要组件。

应用程序的流程如下所示。

  1. 用户选择区块链。
  2. 使用 按排名获取交易所集合 方法获取所有数据。
  3. 将获取的集合数据传递到 NFTCollectionCard 组件中。
  4. 数据显示在应用程序上。
image-20240930222847819.png

让我们开始编码。

步骤 1:创建必要的文件和文件夹

在 src 文件夹中创建一个 components 文件夹。然后,在 components 文件夹中创建 ChainSelector.tsx 和 NFTCollectionCard.tsx 文件。你可以通过在项目目录中的终端中运行以下命令来一次完成所有这些操作。

mkdir src/components
echo > src/components/ChainSelector.tsx && echo > src/components/NFTCollectionCard.tsx
步骤 1:ChainSelector 组件

ChainSelector 组件接受 onChainSelected 函数和 blockchains 属性,它是一个包含区块链密钥、名称和密钥的对象。

在 ChainSelector 内部,我们使用 Object.entries(blockchains) 迭代 blockchains 对象,并为每个区块链创建一个 <option> 元素。区块链的密钥用作选项的值,名称用作显示的文本。

当用户选择不同的区块链时,将使用新的链值调用 onChainSelected 函数。这允许父组件对选择做出反应,并根据所选链更新应用程序状态或重新获取数据。

使用你的代码编辑器打开 src/components/ChainSelector.tsx 文件,然后按如下所示修改该文件。

import React from 'react'

type ChainSelectorProps = {
 onChainSelected: (chain: string) => void
 blockchains: { [key: string]: { name: string; secret: string } }
}

// ChainSelector 函数式组件
const ChainSelector: React.FC<ChainSelectorProps> = ({
 onChainSelected,
 blockchains,
}) => {
 const firstBlockchainKey = Object.keys(blockchains)[0]

 return (
  <div className="inline-block relative w-64">
   {/* 下拉选择元素 */}
   <select
    defaultValue={firstBlockchainKey}
    onChange={e => onChainSelected(e.target.value)}
    className="block appearance-none w-full bg-white border border-gray-400 hover:border-gray-500 px-4 py-2 pr-8 rounded shadow leading-tight focus:outline-none focus:shadow-outline"
   >
    {/* 下拉选项 */}
    {Object.entries(blockchains).map(([key, { name }]) => (
     <option key={key} value={key}>
      {name}
     </option>
    ))}
   </select>
   <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
    <svg
     className="fill-current h-4 w-4"
     xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 20 20"
    >
     <path d="M5.516 7.548c0.436-0.446 1.045-0.481 1.576 0l3.908 3.747 3.908-3.747c0.531-0.481 1.141-0.446 1.576 0 0.436 0.445 0.408 1.197 0 1.615l-4.695 4.502c-0.531 0.481-1.141 0.481-1.672 0l-4.695-4.502c-0.408-.418-0.436-1.17 0-1.615z" />
    </svg>
   </div>
  </div>
 )
}

export default ChainSelector
步骤 2:NFTCollectionCard 组件

NFTCollectionCard 组件旨在显示表布局中的一行,其中包含有关 NFT 集合的详细信息,包括其索引号、名称、图像以及诸如交易量和销售额之类的关键指标。

如果提供了 URL/ 用户名,该组件还会呈现 Discord、Telegram、Twitter 和 Instagram 的社交媒体图标。这些图标在新选项卡中打开相应的社交媒体页面,从而增强了用户参与度。

使用你的代码编辑器打开 src/components/NFTCollectionCard.tsx 文件,然后按如下所示修改该文件。

import React from 'react'
import { SocialIcon } from 'react-social-icons'

// 定义 NFTCollectionCard 组件的属性类型
type NFTCollectionCardProps = {
 index: number // NFT 集合在列表中的索引号
 name: string // NFT 集合的名称
 totalVolume: string // 集合的总销售额
 dailyVolume: string // 每日销售额
 totalSales: string // 销售总数
 dailySales: string // 每日销售额
 averagePrice: string // NFT 的平均价格
 imageUrl: string // 集合图像的 URL
 discordUrl?: string | null // 集合的 Discord 的 URL(可选)
 telegramUrl?: string | null // 集合的 Telegram 的 URL(可选)
 twitterUsername?: string | null // 集合的 Twitter 的用户名(可选)
 instagramUsername?: string | null // 集合的 Instagram 的用户名(可选)
}

const NFTCollectionCard: React.FC<NFTCollectionCardProps> = ({
 index,
 name,
 totalVolume,
 dailyVolume,
 totalSales,
 dailySales,
 averagePrice,
 imageUrl,
 discordUrl,
 telegramUrl,
 twitterUsername,
 instagramUsername,
}) => {
 // 格式化数值以提高可读性的函数
 const formatNumber = (number: string) =>
  Number(number).toLocaleString(undefined, {
   minimumFractionDigits: 2,
   maximumFractionDigits: 2,
  })

 // 社交媒体图标的样式
 const iconStyle = { height: '20px', width: '20px' }

 return (
  // 每个集合卡都是一行
  <tr className="border-b">
   <td className="p-4">{index}</td> {/* 显示索引号 */}
   <td className="flex items-center p-4 space-x-4">
    <img
     className="w-10 h-10 rounded-full"
     src={imageUrl}
     alt={`Collection ${name}`}
    />
    <span className="font-bold">{name}</span>
   </td>
   {/* 显示社交媒体图标 */}
   <td className="p-4">
    {discordUrl && (
     <SocialIcon
      url={discordUrl}
      style={iconStyle}
      className="mr-2"
      target="_blank"
      rel="noopener noreferrer"
     />
    )}
    {telegramUrl && (
     <SocialIcon
      url={telegramUrl}
      style={iconStyle}
      className="mr-2"
      target="_blank"
      rel="noopener noreferrer"
     />
    )}
    {twitterUsername && (
     <SocialIcon
      url={`https://x.com/${twitterUsername}`}
      style={iconStyle}
      className="mr-2"
      target="_blank"
      rel="noopener noreferrer"
     />
    )}
    {instagramUsername && (
     <SocialIcon
      url={`https://instagram.com/${instagramUsername}`}
      style={iconStyle}
      className="mr-2"
      target="_blank"
      rel="noopener noreferrer"
     />
    )}
   </td>
   {/* 显示集合数据 */}
   <td className="p-4 text-right">{formatNumber(totalVolume)} ETH</td>
   <td className="p-4 text-right">{formatNumber(dailyVolume)} ETH</td>
   <td className="p-4 text-right">{totalSales}</td>
   <td className="p-4 text-right">{dailySales}</td>
   <td className="p-4 text-right">{formatNumber(averagePrice)} ETH</td>
  </tr>
 )
}

export default NFTCollectionCard
步骤 3:主 React 组件 - App.tsx

App 组件是应用程序的主要组件。它管理所选区块链和 NFT 集合列表的状态。

该应用程序根据所选区块链从 API 获取 NFT 集合数据。然后,使用 NFTCollectionCard 组件以表格格式显示此数据。

ChainSelector 组件允许用户选择区块链,从而更新应用程序中显示的数据。
该应用程序演示了如何有效地使用诸如 useState 和 useEffect 之类的 React Hook 分别进行状态管理和副作用,以及如何使用 Axios 处理 API 请求。

定义 blockchains 对象

代码中定义的 blockchains 对象是将区块链密钥映射到其显示名称和密钥 Token 的映射。每个密钥(例如“eth-main”、“arbitrum-main”)都对应于特定的区块链。

将占位符值(“ETH_SECRET_TOKEN”、“ARBITRUM_SECRET_TOKEN”等)替换为从相应区块链端点获得的实际密钥。你可以从 blockchains 对象中删除你不打算使用的区块链。

info

通常,密钥不应直接存储在前端代码中。考虑使用后端解决方案来处理敏感密钥并执行安全的 API 调用,尤其是在生产应用程序中。

// 组件和 Hook 导入
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import NFTCollectionCard from './components/NFTCollectionCard'
import ChainSelector from './components/ChainSelector'

// NFT 集合和区块链信息的类型定义
type NFTCollection = {
 key: string
 name: string
 total_volume: string
 one_day_volume: string
 seven_day_volume: string
 thirty_day_volume: string
 total_sales: string
 one_day_sales: string
 seven_day_sales: string
 thirty_day_sales: string
 total_average_price: string
 one_day_average_price: string
 seven_day_average_price: string
 thirty_day_average_price: string
 image_url: string
 discord_url?: string | null
 telegram_url: string | null
 twitter_username?: string | null
 instagram_username?: string | null
}

type BlockchainInfo = {
 name: string
 secret: string
}

type BlockchainObject = {
 [key: string]: BlockchainInfo
}

const App: React.FC = () => {
 // 用于存储 NFT 集合的状态和当前选择的区块链
 const [collections, setCollections] = useState<NFTCollection[]>([])
 const [selectedChain, setSelectedChain] = useState('eth-main')

 // 将区块链密钥映射到其名称和密钥 Token 的对象
 // 你可以从 NFT API With Cached Metadata 给出的 URL 中获取密钥 Token:https://api.blockspan.com/{YOUR_SECRET_TOKEN}/v1/
 const blockchains: BlockchainObject = {
  'eth-main': {
   name: 'Ethereum',
   secret: 'ETH_SECRET_TOKEN',
  },
  'arbitrum-main': {
   name: 'Arbitrum',
   secret: 'ARBITRUM_SECRET_TOKEN',
  },
  'optimism-main': {
   name: 'Optimism',
   secret: 'OPTIMISM_SECRET_TOKEN',
  },
  'poly-main': {
   name: 'Polygon',
   secret: 'POLYGON_SECRET_TOKEN',
  },
 }

 // 用于更新所选区块链的处理程序
 const handleChainSelected = (chain: string) => {
  setSelectedChain(chain)
 }

 // 用于在所选区块链更改时获取 NFT 集合的效果
 useEffect(() => {
  const fetchCollections = async (chain: string) => {
   try {
    const blockchainInfo = blockchains[chain]
    if (!blockchainInfo) {
     console.error('选择了无效的链或未找到详细信息')
     return
    }

    const apiUrl = `https://api.blockspan.com/v1/exchanges/collectionsranking?chain=${chain}&exchange=opensea&ranking=total_volume&page_size=25`
    // 将密钥设置为标头
    const config = {
     headers: {
      'X-API-KEY': blockchainInfo.secret,
     },
    }
    const response = await axios.get(apiUrl, config)
    setCollections(response.data.results)
   } catch (error) {
    console.error('获取 NFT 集合时出错:', error)
   }
  }

  fetchCollections(selectedChain)
 }, [selectedChain]) // eslint-disable-line react-hooks/exhaustive-deps

 // 用于呈现应用程序的 UI 的 JSX
 return (
  <div className="App container mx-auto mt-8">
   <div className="mb-8">
    <h1 className="text-4xl font-bold text-center mb-4">
     {blockchains[selectedChain]?.name || '未知区块链'}上最受欢迎的 NFT 集合
    </h1>
    <div className="flex justify-center">
     <ChainSelector
      onChainSelected={handleChainSelected}
      blockchains={blockchains}
     />
    </div>
   </div>

   <table className="min-w-full">
    <thead className="bg-gray-200">
     <tr>
      <th className="p-4">#</th>
      <th className="p-4">集合</th>
      <th className="p-4">社交</th>
      <th className="p-4 text-right">总交易量</th>
      <th className="p-4 text-right">24 小时交易量</th>
      <th className="p-4 text-right">总销售量</th>
      <th className="p-4 text-right">24 小时销售量</th>
      <th className="p-4 text-right">平均价格</th>
     </tr>
    </thead>
    <tbody>
     {collections.map((collection, index) => (
      <NFTCollectionCard
       key={collection.key}
       index={index + 1} // 从 0 开始添加 1 个数组索引
       name={collection.name}
       totalVolume={collection.total_volume}
       dailyVolume={collection.one_day_volume}
       totalSales={collection.total_sales}
       dailySales={collection.one_day_sales}
       averagePrice={collection.total_average_price}
       imageUrl={collection.image_url}
       discordUrl={collection.discord_url}
       telegramUrl={collection.telegram_url}
       twitterUsername={collection.twitter_username}
      />
     ))}
    </tbody>
   </table>
  </div>
 )
}

export default App
运行应用程序

通过运行以下命令来运行应用程序。

npm start

应用程序现在应该在 http://localhost:3000 上运行

image-20240930222847819.png

结论

祝贺你构建了自己的多链 NFT 分析应用程序!在本指南中,你学习了如何利用带有缓存元数据的 NFT API 插件来访问全面的 NFT 数据、集成多链功能以及以用户友好的界面呈现此信息。你进入 NFT 分析世界的旅程不必止步于此。你可以通过多种方式扩展和改进你的应用程序。

进一步的开发想法

  • 实现分页:目前,该应用程序显示有限数量的集合。添加分页将允许用户浏览所有可用的集合。实现按钮或滚动事件,以便在用户浏览页面或到达列表底部时从 API 加载更多集合。
  • 对集合进行排序:允许用户根据不同的参数(如总交易量、平均价格或总销售量)对集合进行排序。实现一个下拉列表或一组按钮,使用户可以选择排序参数。
  • 过滤选项:实现允许用户根据某些标准(例如稀有度、集合大小或诈骗 / 垃圾邮件评分)查看集合的过滤器。这可能涉及其他 UI 组件,如滑块、复选框或搜索栏。
  • 跨链分析:扩展分析以比较不同区块链的数据,从而深入了解不同平台在 NFT 活动方面的比较情况。
  • 原文链接: https://www.quicknode.com/guides/marketplace/marketplace-add-ons/building-a-multi-chain-nft-analytics-app
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~

登链社区是一个 Web3 开发者社区,通过构建高质量技术内容平台和线下空间,助力开发者成为更好的 Web3 Builder。

登链社区
  • 登链社区网站 : learnblockchain.cn
  • 开发者技能认证 : decert.me
  • B 站 : space.bilibili.com/581611011
  • YouTube : www.youtube.com/@upchain
登链社区

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

登链社区
数据请求中
查看更多

推荐专栏

数据请求中
在 App 打开