· Nacho Coll · Guides  · 9 minit bacaan

Penyimpanan Metadata NFT: Panduan Lengkap IPFS untuk Pencipta NFT

Panduan langkah demi langkah untuk menyimpan metadata NFT pada IPFS. Termasuk corak ERC-721 tokenURI, contoh Python dan JavaScript.

Panduan langkah demi langkah untuk menyimpan metadata NFT pada IPFS. Termasuk corak ERC-721 tokenURI, contoh Python dan JavaScript.

Mencipta NFT memerlukan lebih daripada sekadar penggunaan kontrak pintar — anda memerlukan penyimpanan terdesentralisasi yang boleh dipercayai untuk metadata dan aset anda. Panduan komprehensif ini akan membawa anda langkah demi langkah melalui penyimpanan metadata NFT pada IPFS menggunakan amalan terbaik industri, lengkap dengan contoh kod untuk pembangun Python dan JavaScript.

IPFS Ninja

Mengapa IPFS untuk Penyimpanan Metadata NFT?

Pengehosan web tradisional mewujudkan risiko pemusatan untuk projek NFT. Apabila metadata tinggal pada pelayan konvensional, NFT boleh menjadi “rosak” jika perkhidmatan pengehosan terganggu atau menukar URL. IPFS (InterPlanetary File System) menyelesaikan ini dengan menyediakan:

  • Pengalamatan kandungan tidak boleh ubah: Setiap fail mendapat Content Identifier (CID) unik yang tidak pernah berubah
  • Penyimpanan terdesentralisasi: Kandungan wujud di pelbagai nod di seluruh dunia
  • Pengesahan kriptografi: Integriti fail dijamin melalui pencincangan kandungan
  • URL kalis masa depan: Pautan IPFS berfungsi tanpa had, melindungi nilai jangka panjang

Untuk pemahaman yang lebih mendalam tentang asas IPFS, lihat panduan kami tentang apakah itu IPFS pinning.

Memahami Struktur Metadata ERC-721

Standard ERC-721 mendefinisikan cara metadata NFT harus distrukturkan. Fungsi tokenURI kontrak pintar anda mengembalikan URL yang menunjuk ke metadata JSON mengikut corak ini:

{
  "name": "My Amazing NFT #1",
  "description": "A unique digital artwork showcasing...",
  "image": "ipfs://QmYourImageCIDHere",
  "attributes": [
    {
      "trait_type": "Background",
      "value": "Blue"
    },
    {
      "trait_type": "Rarity",
      "value": "Common"
    }
  ],
  "external_url": "https://yourproject.com/token/1"
}

Medan Metadata Utama

  • name: Tajuk NFT yang dipaparkan dalam dompet dan pasaran
  • description: Maklumat terperinci tentang NFT
  • image: URL IPFS ke aset visual utama
  • attributes: Sifat berdasarkan ciri untuk penapisan dan pengiraan keunikan
  • external_url: Pautan pilihan ke kandungan tambahan atau laman web projek anda

Proses Penyimpanan NFT IPFS Langkah demi Langkah

Langkah 1: Sediakan Aset dan Metadata Anda

Sebelum memuat naik apa-apa, susun fail anda:

  1. Aset utama: Imej, video atau kandungan utama lain
  2. Fail metadata: Fail JSON yang menerangkan setiap NFT
  3. Metadata koleksi: Maklumat tahap koleksi pilihan

Langkah 2: Muat Naik Aset ke IPFS

Mulakan dengan memuat naik aset NFT utama anda (imej, video, dll.) untuk mendapatkan CID IPFS mereka. Anda akan merujuk kepada CID ini dalam fail JSON metadata anda.

Berikut adalah cara memuat naik imej menggunakan Python:

import requests
import base64
import json

def upload_image_to_ipfs(image_path, api_key):
    """Upload an image file to IPFS and return its CID"""
    
    # Read and encode image
    with open(image_path, 'rb') as f:
        image_data = base64.b64encode(f.read()).decode('utf-8')
    
    # Prepare upload payload
    payload = {
        "content": image_data,
        "description": f"NFT Asset: {image_path}"
    }
    
    headers = {
        "Content-Type": "application/json",
        "X-Api-Key": api_key
    }
    
    # Upload to IPFS.NINJA
    response = requests.post(
        "https://api.ipfs.ninja/upload/new",
        headers=headers,
        json=payload
    )
    
    if response.status_code == 200:
        result = response.json()
        print(f"✅ Image uploaded successfully!")
        print(f"CID: {result['cid']}")
        print(f"IPFS URL: {result['uris']['ipfs']}")
        print(f"Gateway URL: {result['uris']['url']}")
        return result['cid']
    else:
        print(f"❌ Upload failed: {response.text}")
        return None

# Example usage
API_KEY = "bws_1234567890abcdef1234567890abcdef"  # Replace with your actual key
image_cid = upload_image_to_ipfs("my-nft-artwork.png", API_KEY)

Langkah 3: Cipta dan Muat Naik JSON Metadata

Setelah anda mempunyai CID aset, cipta fail JSON metadata dan muat naik:

def create_and_upload_metadata(name, description, image_cid, attributes, api_key):
    """Create NFT metadata JSON and upload to IPFS"""
    
    # Create metadata object
    metadata = {
        "name": name,
        "description": description,
        "image": f"ipfs://{image_cid}",
        "attributes": attributes
    }
    
    # Convert to JSON string and encode
    metadata_json = json.dumps(metadata, indent=2)
    metadata_b64 = base64.b64encode(metadata_json.encode('utf-8')).decode('utf-8')
    
    # Upload metadata
    payload = {
        "content": metadata_b64,
        "description": f"NFT Metadata: {name}",
        "metadata": {
            "contentType": "application/json",
            "nftTokenId": name.split('#')[1] if '#' in name else "1"
        }
    }
    
    headers = {
        "Content-Type": "application/json",
        "X-Api-Key": api_key
    }
    
    response = requests.post(
        "https://api.ipfs.ninja/upload/new",
        headers=headers,
        json=payload
    )
    
    if response.status_code == 200:
        result = response.json()
        print(f"✅ Metadata uploaded successfully!")
        print(f"Metadata CID: {result['cid']}")
        return result['cid']
    else:
        print(f"❌ Metadata upload failed: {response.text}")
        return None

# Example usage
attributes = [
    {"trait_type": "Background", "value": "Cosmic Blue"},
    {"trait_type": "Eyes", "value": "Laser"},
    {"trait_type": "Rarity", "value": "Epic"}
]

metadata_cid = create_and_upload_metadata(
    name="Cosmic Warrior #001",
    description="A fierce warrior from the distant galaxies, wielding the power of stars.",
    image_cid=image_cid,
    attributes=attributes,
    api_key=API_KEY
)

Langkah 4: Pelaksanaan JavaScript

Untuk aplikasi web atau projek Node.js, berikut adalah setara JavaScript:

class NFTStorage {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://api.ipfs.ninja';
    }
    
    async uploadFile(fileContent, description) {
        const payload = {
            content: fileContent, // base64 encoded
            description: description
        };
        
        const response = await fetch(`${this.baseUrl}/upload/new`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Api-Key': this.apiKey
            },
            body: JSON.stringify(payload)
        });
        
        if (!response.ok) {
            throw new Error(`Upload failed: ${response.statusText}`);
        }
        
        return await response.json();
    }
    
    async uploadImageFromFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const base64Content = e.target.result.split(',')[1]; // Remove data:image/...;base64, prefix
                    const result = await this.uploadFile(base64Content, `NFT Image: ${file.name}`);
                    resolve(result.cid);
                } catch (error) {
                    reject(error);
                }
            };
            reader.readAsDataURL(file);
        });
    }
    
    async uploadMetadata(name, description, imageCid, attributes = []) {
        const metadata = {
            name,
            description,
            image: `ipfs://${imageCid}`,
            attributes
        };
        
        const metadataJson = JSON.stringify(metadata, null, 2);
        const base64Metadata = btoa(metadataJson);
        
        const result = await this.uploadFile(base64Metadata, `NFT Metadata: ${name}`);
        return result.cid;
    }
}

// Usage example
const storage = new NFTStorage('bws_1234567890abcdef1234567890abcdef'); // Replace with your key

// Upload process
async function createNFT() {
    try {
        // Assuming you have a file input element
        const fileInput = document.getElementById('nft-image');
        const imageFile = fileInput.files[0];
        
        console.log('Uploading image...');
        const imageCid = await storage.uploadImageFromFile(imageFile);
        console.log(`Image uploaded: ${imageCid}`);
        
        console.log('Uploading metadata...');
        const metadataCid = await storage.uploadMetadata(
            'Galaxy Explorer #042',
            'A mysterious explorer traversing the cosmic void.',
            imageCid,
            [
                { trait_type: 'Class', value: 'Explorer' },
                { trait_type: 'Galaxy', value: 'Andromeda' },
                { trait_type: 'Rarity', value: 'Legendary' }
            ]
        );
        
        console.log(`Metadata uploaded: ${metadataCid}`);
        console.log(`Token URI: ipfs://${metadataCid}`);
        
    } catch (error) {
        console.error('Upload failed:', error);
    }
}

Melaksanakan tokenURI dalam Kontrak Pintar Anda

Setelah metadata anda dimuat naik ke IPFS, laksanakan fungsi tokenURI dalam kontrak ERC-721 anda:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MyNFTCollection is ERC721, Ownable {
    mapping(uint256 => string) private _tokenURIs;
    string private _baseTokenURI;
    
    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
    
    function setTokenURI(uint256 tokenId, string memory uri) external onlyOwner {
        require(_exists(tokenId), "Token does not exist");
        _tokenURIs[tokenId] = uri;
    }
    
    function setBaseURI(string memory baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
    }
    
    function tokenURI(uint256 tokenId) public view virtual override returns (string) {
        require(_exists(tokenId), "Token does not exist");
        
        string memory _tokenURI = _tokenURIs[tokenId];
        
        // Return specific token URI if set
        if (bytes(_tokenURI).length > 0) {
            return _tokenURI;
        }
        
        // Fall back to base URI + token ID pattern
        if (bytes(_baseTokenURI).length > 0) {
            return string(abi.encodePacked(_baseTokenURI, tokenId.toString()));
        }
        
        return "";
    }
    
    function mintWithURI(address to, uint256 tokenId, string memory uri) external onlyOwner {
        _mint(to, tokenId);
        _tokenURIs[tokenId] = uri;
    }
}

Operasi Berkelompok untuk Koleksi Besar

Untuk koleksi NFT yang besar, operasi berkelompok menjimatkan masa dan kos gas:

def batch_upload_collection(collection_data, api_key):
    """Upload an entire NFT collection in batches"""
    
    print(f"Starting batch upload of {len(collection_data)} NFTs...")
    results = []
    
    for i, nft_data in enumerate(collection_data):
        print(f"Processing NFT {i+1}/{len(collection_data)}: {nft_data['name']}")
        
        try:
            # Upload image
            image_cid = upload_image_to_ipfs(nft_data['image_path'], api_key)
            
            if image_cid:
                # Upload metadata
                metadata_cid = create_and_upload_metadata(
                    name=nft_data['name'],
                    description=nft_data['description'],
                    image_cid=image_cid,
                    attributes=nft_data['attributes'],
                    api_key=api_key
                )
                
                if metadata_cid:
                    results.append({
                        'token_id': i + 1,
                        'name': nft_data['name'],
                        'image_cid': image_cid,
                        'metadata_cid': metadata_cid,
                        'token_uri': f"ipfs://{metadata_cid}"
                    })
                    
        except Exception as e:
            print(f"❌ Error processing {nft_data['name']}: {e}")
    
    print(f"✅ Batch upload complete! {len(results)} NFTs processed successfully.")
    return results

# Example collection data
collection_data = [
    {
        'name': 'Cosmic Warrior #001',
        'description': 'A fierce warrior from distant galaxies.',
        'image_path': 'images/warrior_001.png',
        'attributes': [
            {'trait_type': 'Class', 'value': 'Warrior'},
            {'trait_type': 'Rarity', 'value': 'Epic'}
        ]
    },
    # Add more NFTs...
]

results = batch_upload_collection(collection_data, API_KEY)

Amalan Terbaik untuk Penyimpanan Metadata NFT

1. Gunakan Nama Fail Deskriptif

Apabila memuat naik ke IPFS, gunakan penerangan yang bermakna untuk membantu organisasi:

payload = {
    "content": base64_content,
    "description": f"Collection: {collection_name} | Token: {token_id} | Type: {file_type}"
}

2. Laksanakan Pengendalian Ralat yang Betul

Sentiasa kendalikan kegagalan muat naik dengan elegan:

import time

def upload_with_retry(upload_function, max_retries=3, delay=2):
    """Upload with exponential backoff retry logic"""
    
    for attempt in range(max_retries):
        try:
            return upload_function()
        except Exception as e:
            if attempt == max_retries - 1:
                raise e
            print(f"Attempt {attempt + 1} failed: {e}. Retrying in {delay} seconds...")
            time.sleep(delay)
            delay *= 2  # Exponential backoff

3. Sahkan Struktur Metadata

Pastikan metadata anda mematuhi standard:

def validate_metadata(metadata):
    """Validate NFT metadata structure"""
    required_fields = ['name', 'description', 'image']
    
    for field in required_fields:
        if field not in metadata:
            raise ValueError(f"Missing required field: {field}")
    
    if not metadata['image'].startswith('ipfs://'):
        raise ValueError("Image must be an IPFS URL")
    
    if 'attributes' in metadata:
        for attr in metadata['attributes']:
            if 'trait_type' not in attr or 'value' not in attr:
                raise ValueError("Invalid attribute structure")
    
    return True

Memilih Perkhidmatan IPFS Pinning yang Tepat

Apabila memilih perkhidmatan IPFS pinning untuk projek NFT anda, pertimbangkan:

  • Kebolehpercayaan: Masa operasi terjamin untuk penyimpanan jangka panjang
  • Prestasi: Kelajuan pengambilan pantas di seluruh dunia
  • Harga: Kos efektif untuk saiz koleksi anda
  • Ciri-ciri: Keupayaan API, analitik dan alat pembangun

Untuk perbandingan terperinci perkhidmatan pinning, baca perbandingan kami IPFS Ninja vs Pinata dan panduan kami tentang perkhidmatan IPFS pinning terbaik.

Ciri-ciri Lanjutan: Get Tersuai dan Analitik

IPFS Ninja menawarkan ciri-ciri tambahan untuk projek NFT profesional:

Konfigurasi Get Tersuai

Cipta get IPFS berjenama untuk koleksi anda:

// Access your NFT through a custom gateway
const customGateway = 'https://my-collection.gw.ipfs.ninja';
const nftUrl = `${customGateway}/ipfs/${metadataCid}`;

Analitik Muat Naik

Pantau penggunaan storan NFT dan corak akses melalui analitik papan pemuka, membantu anda memahami prestasi koleksi dan mengoptimumkan kos penyimpanan.

Menyelesaikan Masalah Biasa

Metadata Tidak Dimuatkan

  • Sahkan URL IPFS menggunakan protokol ipfs://
  • Periksa metadata JSON adalah sah
  • Pastikan perkhidmatan pinning sedang mengekalkan kandungan

Imej Tidak Dipaparkan

  • Sahkan CID imej adalah betul dalam metadata
  • Uji URL imej dalam get IPFS
  • Sahkan format fail imej serasi dengan web

Ralat Anggaran Gas

  • Pastikan fungsi tokenURI mengembalikan rentetan yang sah
  • Periksa rujukan kitaran dalam metadata
  • Sahkan semua CID IPFS sebelum minting

Memantau dan Mengekalkan Storan NFT Anda

Selepas menggunakan koleksi anda:

  1. Pemeriksaan Kesihatan Berkala: Sahkan metadata dan imej kekal boleh diakses
  2. Sandar CID Penting: Simpan rekod semua pengecam kandungan yang dimuat naik
  3. Pantau Analitik: Jejaki corak akses dan penggunaan storan
  4. Rancang untuk Skala: Pertimbangkan menaik taraf perkhidmatan pinning anda apabila koleksi anda berkembang

Untuk butiran lanjut tentang menguruskan muat naik secara programatik, lihat tutorial API muat naik IPFS kami.

Kesimpulan

Menyimpan metadata NFT pada IPFS memastikan aset digital anda kekal boleh diakses dan bernilai dalam jangka panjang. Dengan mengikuti panduan ini, anda telah belajar:

  • Menstrukturkan metadata yang mematuhi ERC-721
  • Memuat naik aset dan metadata menggunakan Python dan JavaScript
  • Melaksanakan fungsi tokenURI yang sesuai
  • Mengendalikan operasi berkelompok untuk koleksi besar
  • Menerapkan amalan terbaik untuk penggunaan pengeluaran

Kombinasi seni bina IPFS terdesentralisasi dan perkhidmatan pinning yang boleh dipercayai mewujudkan asas untuk projek NFT yang berjaya yang tahan ujian masa.

Bersedia untuk mulakan dengan pinning? Cipta akaun percuma — 50 fail, 1 GB storan, 2 GB lebar jalur/bulan. Tiada kad kredit diperlukan.

Kembali ke Blog

Artikel Berkaitan

Lihat Semua Artikel »