You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React应用获取Solana链CNFT元数据的技术问题求助

问题描述

我正在开发一款React应用,用于展示Solana区块链上的压缩非同质化代币(CNFT)的元数据。在尝试通过Solana交易签名获取元数据时遇到了问题,以下是我使用的相关代码:

import axios from 'axios';
import { useEffect, useState } from 'react';
import { Connection, PublicKey } from '@solana/web3.js';

function CNFTDisplay() {
    const [metadata, setMetadata] = useState(null);

    useEffect(() => {
    // 定义CNFT交易的签名
        const signature = "3MFt6C5pn1kouaw5A8Jmm6X3rm9yFA5q1wwsk9WDMX3oLVnX1dHfUa1zHqTZWdJbjRmhWhGctsp4rJSzFgud8ZqJ";

        // 定义Solana RPC端点的URL
        const rpc_url = "https://api.devnet.solana.com";

        // 连接到Solana网络
        const connection = new Connection(rpc_url);

        // 根据签名获取交易信息
        connection.getTransaction(signature).then(transaction_info => {
        // 从交易信息中提取代币ID
        const token_id = transaction_info?.meta?.innerInstructions?.[0]?.toString();

        // 定义元数据端点的URL
        const metadata_url = `https://api.devnet.solana.com/metadata/accounts/${token_id}`;

        // 向元数据端点发送请求
        axios.get(metadata_url)
            .then(response => {
            setMetadata(response.data);
            })
            .catch(error => {
            console.error(error);
            });
        });
    }, []);

    if (metadata === null) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            <h1>{metadata.name}</h1>
            <p>{metadata.description}</p>
            <img src={metadata.image} alt={metadata.name} />
        </div>
    );
    }

export default CNFTDisplay;
问题分析

你的代码存在3个核心问题:

  1. Token ID提取逻辑错误:transaction_info?.meta?.innerInstructions?.[0]?.toString()无法获取有效CNFT资产ID,innerInstructions是交易内部指令数组,直接toString()只会得到无意义字符串。压缩NFT的资产ID需要从交易中Bubblegum程序的指令里解析。
  2. 元数据请求端点错误:Solana官方RPC没有/metadata/accounts/${token_id}端点,压缩NFT的元数据需通过Metaplex数字资产标准(DAS)API获取,而非直接调用Solana RPC。
  3. 交易信息参数不全:调用getTransaction时未指定足够参数,默认返回的信息不包含解析CNFT所需的完整指令细节。
修正后的代码
import axios from 'axios';
import { useEffect, useState } from 'react';
import { Connection, PublicKey } from '@solana/web3.js';

// Devnet环境下的Bubblegum程序公钥
const BUBBLEGUM_PROGRAM_ID = new PublicKey('BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY');

function CNFTDisplay() {
    const [metadata, setMetadata] = useState(null);
    const [error, setError] = useState(null);

    useEffect(() => {
        const fetchCNFTMetadata = async () => {
            const signature = "3MFt6C5pn1kouaw5A8Jmm6X3rm9yFA5q1wwsk9WDMX3oLVnX1dHfUa1zHqTZWdJbjRmhWhGctsp4rJSzFgud8ZqJ";
            const rpcUrl = "https://api.devnet.solana.com";
            const dasApiUrl = "https://api.devnet.metaplex.com";

            const connection = new Connection(rpcUrl);

            try {
                // 获取完整交易信息,指定参数确保解析指令数据
                const transactionInfo = await connection.getTransaction(signature, {
                    commitment: 'confirmed',
                    encoding: 'jsonParsed',
                    maxSupportedTransactionVersion: 0
                });

                if (!transactionInfo) {
                    throw new Error('未找到目标交易信息');
                }

                // 遍历交易指令,提取Bubblegum程序中的CNFT资产ID
                let assetId = null;
                const instructions = transactionInfo.transaction.message.instructions;
                for (const instr of instructions) {
                    if (instr.programId.equals(BUBBLEGUM_PROGRAM_ID)) {
                        // 解析mintV1指令中的资产ID(字节位置8-40)
                        if (instr.data.length >= 40) {
                            const assetIdBytes = instr.data.slice(8, 40);
                            assetId = new PublicKey(assetIdBytes).toString();
                            break;
                        }
                    }
                }

                if (!assetId) {
                    throw new Error('从交易中未提取到CNFT资产ID');
                }

                // 通过Metaplex DAS API获取CNFT元数据
                const metadataResponse = await axios.get(`${dasApiUrl}/v1/assets/${assetId}`, {
                    params: {
                        displayOptions: JSON.stringify({ showMetadata: true })
                    }
                });

                setMetadata(metadataResponse.data.result.metadata);
            } catch (err) {
                console.error('获取元数据失败:', err);
                setError(err.message);
            }
        };

        fetchCNFTMetadata();
    }, []);

    if (error) {
        return <div>错误: {error}</div>;
    }

    if (metadata === null) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            <h1>{metadata.name}</h1>
            <p>{metadata.description}</p>
            <img src={metadata.image} alt={metadata.name} style={{ maxWidth: '400px' }} />
        </div>
    );
}

export default CNFTDisplay;
关键说明
  • 调用getTransaction时指定了encoding: 'jsonParsed'和maxSupportedTransactionVersion,确保能解析完整的交易指令数据。
  • 通过识别Bubblegum程序指令提取CNFT资产ID(实际项目推荐使用@metaplex-foundation/jsSDK来更可靠地解析压缩NFT指令)。
  • 使用Metaplex DAS API获取元数据,该API专门用于处理Solana上的数字资产(包括压缩NFT)。

内容的提问来源于stack exchange,提问作者Tadeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:11:33