只用 React 和 Chainbase API,如何创建一个自己的 NFT Gallery

  • Chainbase
  • 更新于 2023-11-24 19:15
  • 阅读 1421

本指南的目的是为读者提供有关创建NFT档案的说明,重点关注任务所需的关键技术框架和工具。通过使用 Chainbase,一个提供用户友好API端点用于NFT管理的平台,用户可以全面了解如何有效处理NFTs。

原文作者:masterdai

Introduction

非同质化代币(NFTs)在数字艺术和收藏品市场引起了革命,标志着我们对数字领域内所有权和价值的感知发生了重大变化。

本指南的目的是为读者提供有关创建NFT档案的说明,重点关注任务所需的关键技术框架和工具。通过使用Chainbase,一个提供用户友好API端点用于NFT管理的平台,用户可以全面了解如何有效处理NFTs。

在这个前端demo中,我们需要利用两个Chainbase API,并将它们结合起来实现相对复杂的功能。例如,使用ENS地址进行NFT查询,以及通过连接您的钱包地址并输入NFT合约地址进行精确搜索。此外,可以通过调整滚动条来探索多链NFTs。

nftdemo.gif

https://nftdemo-lime.vercel.app/

前期准备

技术要求: 要创建一个NFT档案,您将需要一些关键的工具和技术。首要要求是对React的深刻理解,因为它将是我们用于构建应用程序前端的主要库。此外,对Axios和Fetch的了解对于处理HTTP请求至关重要。这些库将使我们能够有效地与API进行交互。

设置环境:

  • 安装Node.js: 确保您的系统上已安装Node.js,因为它是运行React应用程序所需的。您可以从Node.js官方网站下载它。
  • 设置React: 如果还没有,请使用Create React App设置一个新的React项目,以快速启动。您可以在终端中运行命令 npx create-react-app my-nft-profile 来完成此操作。
  • Axios和Fetch: 在项目目录中运行 npm install axios 安装Axios。Fetch内置在现代浏览器中,因此如果使用Chrome或Firefox等浏览器,则无需额外安装。
  • 其他设置: 确保您的开发环境包括一个代码编辑器(如Visual Studio Code),并熟悉基本的命令行操作,因为它们将在整个开发过程中经常使用。

有了这些工具和技术的设置,您就可以开始构建您的NFT档案了。

编写NFT演示教程的代码

在本节中,我们将详细介绍将编码过程分解为NFT演示的各个部分的步骤,包括每个部分的代码示例和解释。

第1步:BlockchainSelector 组件

  • 目的: 此组件允许用户选择区块链网络。
  • 代码解释
    • 自定义钩子 - useChainId 管理所选区块链网络的状态。
    • 组件设置: 使用 useChainId 钩子进行网络选择,并在更改时更新所选的链ID。
import React, { useState, useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import styles from '../styles/Home.module.css';

const capitalizeFirstLetter = (string) => {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

const useChainId = (initialNetwork) => {
  const networkToChainId = useMemo(() => ({
    ethereum: 1,
    polygon: 137,
    bsc: 56,
    avalanche: 43114,
    arbitrum: 42161,
    optimism: 10,
    base: 8453,
    zksync: 324,
  }), []);

  const [selectedNetwork, setSelectedNetwork] = useState(initialNetwork);
  const selectedChainId = networkToChainId[selectedNetwork];

  return {
    selectedNetwork,
    setSelectedNetwork,
    selectedChainId,
    networkToChainId 
  };
};

const BlockchainSelector = ({ setSelectedChainId }) => {
  const { selectedNetwork, setSelectedNetwork, selectedChainId, networkToChainId } = useChainId('ethereum');

  useEffect(() => {
    setSelectedChainId(selectedChainId);
  }, [selectedChainId]);

  const handleChange = (event) => {
    setSelectedNetwork(event.target.value);
  };

  return (
    <div className={styles.blockchainSelectorContainer}>
      <label htmlFor="blockchainSelector" className={styles.blockchainSelectorLabel}>
        Select a Blockchain Network:
      </label>
      <select id="blockchainSelector" value={selectedNetwork} onChange={handleChange}>
        {Object.keys(networkToChainId).map((network) => (
          <option key={network} value={network}>
            {capitalizeFirstLetter(network)}
          </option>
        ))}
      </select>
    </div>
  );
};

BlockchainSelector.propTypes = {
  setSelectedChainId: PropTypes.func.isRequired,
};

export default BlockchainSelector;

第2步:NftCard 组件

  • 目的: 显示单个NFT的详细信息,包括图像和元数据。
  • 代码解释
    • 实用函数
      • convertToHttpUrl:将IPFS URL转换为显示。
      • handleImageError:处理图像加载期间的错误。
    • 组件渲染:显示NFT的详细信息,如名称、符号、令牌ID和图像。
import React, { useState, useEffect } from 'react';

const convertToHttpUrl = (url) => {
  if (typeof url === 'string' && url.startsWith('ipfs://')) {
    return `https://cloudflare-ipfs.com/ipfs/${url.split('ipfs://')[1]}`;
  }
  return url;
};

const handleImageError = (e,setImageError) => {
  const ipfsPattern = /ipfs\/(Qm[1-9A-Za-z]{44}\/?.*)/;
  const match = e.target.src.match(ipfsPattern);
  if (match) {
    e.target.src = `https://cloudflare-ipfs.com/ipfs/${match[1]}`;
  }
  else {
    setImageError(true);
  }
};

const NftCard = ({ nft }) => {
  const maxTokenIdLength = 10;
  const truncatedTokenId = nft.token_id.length > maxTokenIdLength ? nft.token_id.substring(0, maxTokenIdLength) + '...' : nft.token_id;
  const imageUri = nft.image_uri || (nft.metadata ? nft.metadata.image : '');
  const imageUrl = convertToHttpUrl(imageUri);
  const [isVideo, setIsVideo] = useState(false);
  const [imageError, setImageError] = useState(false);
  //console.log('Image URL:', imageUrl); 

  useEffect(() => {
    fetch(imageUrl)
      .then((response) => {
        if (!response.ok) {
          throw new Error('Failed to fetch image');
        }
        const contentType = response.headers.get('Content-Type');
        if (contentType && contentType.startsWith('video')) {
          setIsVideo(true);
        }
      })
      .catch((error) => {
        // This is where errors can be logged or default images can be set, but it will not cause unhandled runtime errors.
        console.error('Error fetching image:', error);
      });
  }, [imageUrl]);

  return (
    <div style={{ width: '25%', padding: '10px', border: '1px solid #ccc' }}>
      {isVideo ? (
        <video src={imageUrl} controls style={{ width: '100%' }} />
      ): imageError ? (
        <div>NFT not shown</div> // If the image fails to load, display this message.
      ) 
       : (
          <img src={imageUrl} alt={nft.name} style={{ width: '100%' }} onError={(e) => handleImageError(e, setImageError)} />
        )}
      <h3>{nft.name}</h3>
      <p><strong>Symbol:</strong> {nft.symbol}</p>
      <p><strong>Token ID:</strong> <span title={nft.token_id}>{truncatedTokenId}</span></p>
      <p><strong>Contract Address:</strong> {nft.contract_address}</p>
    </div>
  );
};

export default NftCard;

第3步:SearchBar 组件

  • 目的: 处理用户输入和NFT搜索的MetaMask集成。
  • 代码解释
    • 状态管理:管理用户输入的地址和与MetaMask连接的地址。
    • MetaMask功能:包括连接和断开功能。
    • 搜索功能:在用户输入时触发搜索。
import React, { useState } from 'react';

const SearchBar = ({ onSearch }) => {
    const [inputAddress, setInputAddress] = useState(''); // 用户手动输入的地址
    const [connectedAddress, setConnectedAddress] = useState(''); // 从MetaMask连接的地址
    const [contractAddress, setContractAddress] = useState('');

    const connectMetaMask = async () => {
        if (!window.ethereum) {
            alert('Please install MetaMask first.');
            return;
        }

        let accounts;
        try {
            accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
            setConnectedAddress(accounts[0]);
            setInputAddress(''); // 连接后清除地址
        } catch (error) {
            alert('You rejected the request.');
        }
    };

    const disconnectWallet = () => {
        setConnectedAddress(''); // 清除连接的MetaMask地址
        setInputAddress(''); // 同时清除输入地址
    };

    const handleSearch = () => {
        const addressToSearch = connectedAddress || inputAddress;
        onSearch(addressToSearch, contractAddress);
    };

    return (
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
            {connectedAddress ? (
                <>
                    <span>Connected Address: {connectedAddress}</span>
                    <button onClick={disconnectWallet}>Disconnect Wallet</button>
                </>
            ) : (
                <>
                    <button onClick={connectMetaMask}>Connect MetaMask</button>
                    <input
                        type="text"
                        placeholder='Your ETH address or ENS name'
                        value={inputAddress}
                        onChange={(e) => setInputAddress(e.target.value)}
                        style={{ margin: '10px 0', width: '300px' }}
                    />
                </>
            )}
            <input 
                type="text"
                placeholder='NFT Contract address (optional)'
                value={contractAddress}
                onChange={(e) => setContractAddress(e.target.value)}
                style={{ margin: '10px 0', width: '300px' }}
            />
            <button onClick={handleSearch}>Search</button>
        </div>
    );
};

export default SearchBar;

第4步:Home 组件

  • 目的: 作为NFT档案应用程序的主容器。
  • 代码解释
    • 状态管理:管理NFT数据和所选的区块链ID的状态。
    • 搜索处理:根据搜索参数调用API获取NFT数据。
    • UI组成:集成应用程序UI的所有子组件。
import React, { useState } from 'react';
import axios from 'axios';
import SearchBar from '../components/SearchBar';
import NftCard from '../components/NftCard';
import BlockchainSelector from '../components/BlockchainSelector';  

const Home = () => {
  const [nftData, setNftData] = useState(null);
  const [selectedChainId, setSelectedChainId] = useState('');

  const handleSearch = async (address, contractAddress) => {
    setNftData(null);
    try {
      const response = await axios.get(`/api/chainbaseApi?address=${address}&contract_address=${contractAddress}&chain_id=${selectedChainId}`);
      setNftData(response.data.data);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div style={{ textAlign: 'center' }}>
      <img src="/logo.png" alt="Chainbase Logo" style={{ marginTop: '20px', width: '300px', height: '50px' }} />

      <BlockchainSelector setSelectedChainId={setSelectedChainId} />
      <SearchBar onSearch={handleSearch} />

      {nftData && nftData.length > 0 ? (
        <div>
          <h2>NFTs for Address: {nftData[0].owner}</h2>
          <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center' }}>
            {nftData.map((nft) => (
              <NftCard key={`${nft.contract_address}-${nft.token_id}`} nft={nft} />
            ))}
          </div>
        </div>
      ) : (
        <div></div>
      )}
    </div>
  );
};

export default Home;

该 NFT 演示中的每个组件都旨在处理特定功能,确保明确的关注点分离。这种模块化方法有助于有效地维护和扩展应用程序。

第五步:详细解释Chainbase API与ENS API的集成使用

在这一步中,我们将深入探讨将Chainbase API集成到我们的NFT演示中的关键方面,特别关注使用ENS API解析以太坊地址的用途。

  • API处理程序设置
    • 目的:这个服务器端的函数充当中介,处理来自前端的请求,处理它们,并与Chainbase API通信以获取NFT数据。
  • 代码解析
    • 初始设置和CORS配置:设置处理程序并配置CORS以允许跨域请求。
export default async function handler(req, res) {
  // Logging and CORS setup
}
  • 处理ENS名称
    • ENS API调用:如果提供的地址是ENS名称(以'.eth'结尾),则代码调用Chainbase ENS API将其解析为标准的以太坊地址。
if (address.endsWith('.eth')) {
  // Fetching from Chainbase ENS API
  // Convert ENS to Ethereum address
}
  • 构建Chainbase API请求URL

    • 在将ENS名称解析为以太坊地址(或使用直接提供的以太坊地址)之后,该函数构建了用于Chainbase API请求的URL。
    • 它附加了chain_idaddresscontract_address等参数到基本URL。
    const baseUrl = `https://api.chainbase.online/v1/account/nfts?chain_id=${chainId}`;
    let targetUrl = `${baseUrl}&address=${address}&limit=100`;
    if (query.contract_address) {
      targetUrl += `&contract_address=${query.contract_address}`;
    }
    
  • 从Chainbase API获取数据

    • API请求:代码使用fetch函数通过构建的URL向Chainbase API发出GET请求。
    • 处理响应:然后解析来自Chainbase API的响应并发送回前端。
const backendResponse = await fetch(targetUrl, {
  headers: {
    accept: 'application/json',
    'x-api-key': process.env.CHAINBASE_API_KEY,
  },
});
// Processing and sending the response to the front-end
  • 错误处理:该函数包括错误处理以处理API调用期间可能出现的任何问题,确保前端在失败的情况下也能收到适当的响应。
try {
  // Chainbase API request and response handling
} catch (error) {
  res.status(500).json({ error: 'Error' });
}

这个处理程序函数对于NFT演示的功能至关重要,因为它无缝地集成了ENS名称解析和从Chainbase API检索NFT数据。理解这个函数提供了一个全面的视图,说明了如何实现后端逻辑以支持Web应用程序的前端功能。

5. 测试与部署

Testing Process

在部署NFT个人资料应用程序之前,在本地开发环境中进行彻底的测试非常重要。

  1. 启动本地开发服务器
    • 在终端中运行npm run dev。此命令启动开发服务器,使您可以在本地访问应用程序。
    • 默认情况下,应用程序应该在http://localhost:3000或终端中提供的类似URL上可访问。
  2. 测试功能
    • 在Web浏览器中导航应用程序,确保所有组件都正确呈现。
    • 通过输入不同的地址、ENS名称和合同地址来测试搜索功能和区块链网络选择。确保应用程序正确显示NFT数据或适当处理错误。
  3. 检查控制台日志
    • 监视控制台,查看可能指示代码问题的任何错误或警告。
    • 验证API调用是否正确执行,并且响应是否按预期处理。

部署指南

一旦您的应用程序经过测试并准备就绪,您可以将其部署到诸如Vercel之类的云平台以供公共访问。

  1. 设置部署
    • 如果尚未注册,请在Vercel上注册帐户。
    • 运行npm install -g vercel或按照Vercel文档中的说明安装Vercel CLI。
  2. 为部署准备您的项目
    • 确保项目的package.json文件正确设置了启动脚本。
    • 在Vercel的项目设置中添加任何环境变量(如您的Chainbase API密钥)这些可以在Vercel仪表板上的项目设置中添加。
  3. 部署到Vercel
    • 在终端中导航到项目目录。
    • 运行命令vercel以启动部署。Vercel CLI将指导您完成此过程。
    • 部署后,Vercel将提供一个URL以访问您的部署应用程序。
  4. 验证部署
    • 访问提供的URL,确保您的NFT个人资料应用程序在实时环境中可以访问并正常运行。

部署到Vercel等平台提供了易用性、可扩展性和与各种前端框架的集成的优势。记得保持API密钥和敏感数据的安全,并避免在客户端代码中公开它们。

6. Conclusion

在本教程中,我们介绍了使用现代Web技术创建NFT个人资料的关键步骤。我们首先通过使用React和Axios等工具设置了我们的环境。然后,我们深入探讨了编码过程,其中我们开发了几个组件,如BlockchainSelectorNftCardSearchBar,每个在我们的应用程序中扮演着重要的角色。

我们还探讨了如何集成Chainbase API以获取NFT数据,包括处理以太坊名称服务(ENS)地址。强调了测试和部署的重要性,确保我们的应用程序是健壮且可访问的。

NFT个人资料的创建不仅突显了区块链技术的实际应用,还展示了NFT在代表数字所有权和身份方面在不断演变的Web空间中的潜力。

拓展阅读和信息

为了加深对本教程中使用的技术和概念的理解,考虑查阅以下资源:

  1. IPFS(星际文件系统)
    • 了解IPFS的工作原理以及在NFT上下文中处理去中心化文件存储的重要性。
    • IPFS文档
  2. 处理NFT中的不同媒体类型
    • 了解如何识别和处理NFT元数据中的各种媒体类型,如GIF或视频。
    • 了解NFT元数据
  3. 高级区块链概念
    • 更深入地了解区块链技术及其应用,特别是在NFT和数字所有权的背景下。
    • 区块链基础知识
  4. React和Next.js文档
  5. Vercel部署指南

通过本教程的学习和探索这些额外的资源,您将为深入了解NFT和区块链技术的世界以及在Web开发和数字资产创建中解锁新的可能性做好充分准备。

原文链接:Create Your Own NFT Gallery with React and Chainbase API

  • 原创
  • 学分: 10
  • 分类: NFT
  • 标签: API 
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Chainbase
Chainbase
0x7C46...d02D
Chainbase 是领先的 Web3 数据基础设施,帮助开发者轻松访问加密数据,并支持对数据的大规模索引、转换和使用。