Standart SPL Token'ları ad, sembol veya görsel gibi metadata içermez. Metaplex Token Metadata Programı bu sorunu her token mint'ine bağlı bir metadata hesabı oluşturarak çözer.
Bu kılavuz, standart SPL Token'ları ve Token-2022 için kullanılabilen Metaplex Token Metadata Programını kapsar. Token-2022 Metadata Extension'ı kullanmak için, metadata'yı doğrudan mint hesabında saklayan Metadata Extension kılavuzuna bakın.
Token Metadata Nasıl Çalışır
Token Metadata Programı, her token mint'i için bir Program Derived Address (PDA) oluşturur. Bu metadata hesabı, token'ın adı ve sembolü gibi zincir üstü bilgileri ve zincir dışı JSON metadata'ya (görseller, açıklamalar vb.) işaret eden bir URI'ı depolar.
┌─────────────────┐ ┌─────────────────────┐│ Mint Account │ │ Metadata Account ││ │ │ (PDA) ││ - Supply │◄──────│ - Name ││ - Decimals │ │ - Symbol ││ - Authority │ │ - URI │└─────────────────┘ │ - Seller Fee ││ - Creators │└─────────────────────┘
Metadata PDA'sı şu seed'lerden türetilir:
["metadata", program_id, mint_address]
Metadata ile Token Oluşturma
createV1 talimatı, hem mint account hem de metadata'sını tek bir işlemde
oluşturur.
Typescript
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import {getCreateV1InstructionAsync,TokenStandard} from "@metaplex-foundation/mpl-token-metadata-kit";// Create connectionconst rpc = createSolanaRpc("http://127.0.0.1:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");// Generate keypairsconst payer = await generateKeyPairSigner();const mint = await generateKeyPairSigner();// Fund payerawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: payer.address,lamports: lamports(1_000_000_000n),commitment: "confirmed"});// Create fungible token with metadataconst createInstruction = await getCreateV1InstructionAsync({mint,authority: payer,payer,name: "My Token",symbol: "MTK",uri: "https://example.com/token.json",sellerFeeBasisPoints: 0,tokenStandard: TokenStandard.Fungible});// Build and send transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(payer, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([createInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });console.log("Mint Address:", mint.address);
Token Metadata'sını Çekme
Mevcut token'lar için metadata'nın nasıl çekileceğini öğrenmek için Fetch Token Metadata cookbook tarifine bakın.
Token Metadata'sını Güncelleme
Güncelleme yetkisi, hesap değiştirilebilir durumdaysa metadata'yı değiştirebilir.
import {appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import {getUpdateV1InstructionAsync,findMetadataPda,fetchMetadata} from "@metaplex-foundation/mpl-token-metadata-kit";const rpc = createSolanaRpc("http://127.0.0.1:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");// authority must be a KeyPairSigner with update authorityconst mintAddress = "YOUR_MINT_ADDRESS";// Fetch current metadata to preserve existing valuesconst [metadataAddress] = await findMetadataPda({ mint: mintAddress });const currentMetadata = await fetchMetadata(rpc, metadataAddress);// Update metadata (must provide all data fields)const updateInstruction = await getUpdateV1InstructionAsync({mint: mintAddress,authority, // Update authority signerpayer: authority,data: {name: "Updated Token Name",symbol: "UPD",uri: "https://example.com/updated-token.json",sellerFeeBasisPoints: 100, // 1%creators:currentMetadata.data.creators.__option === "Some"? currentMetadata.data.creators.value: null}});// Build and send transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(authority, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([updateInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });console.log("Metadata updated successfully");
Token Standartları
Token Metadata Programı farklı token standartlarını destekler:
| Standart | Açıklama | Kullanım Alanı |
|---|---|---|
Fungible | Metadata'lı standart fungible token | Para birimleri, puanlar |
FungibleAsset | Benzersiz bir varlığı temsil eden fungible token | Yarı-fungible öğeler |
NonFungible | Master Edition'lı NFT | 1/1 sanat eseri |
ProgrammableNonFungible | Zorunlu telif haklarına sahip NFT | Yaratıcı telifleri |
NonFungibleEdition | Bir NFT'nin basılı kopyası | Sınırlı edisyonlar |
ProgrammableNonFungibleEdition | Zorunlu telif haklarına sahip basılı kopya | Sınırlı edisyonlar |
import { TokenStandard } from "@metaplex-foundation/mpl-token-metadata-kit";// For fungible tokenstokenStandard: TokenStandard.Fungible;// For NFTstokenStandard: TokenStandard.NonFungible;// For programmable NFTs (enforced royalties)tokenStandard: TokenStandard.ProgrammableNonFungible;
Zincir Dışı Metadata Formatı
uri alanı, genişletilmiş metadata içeren bir JSON dosyasına işaret eder.
Standart format,
Metaplex Token Metadata Standardını
takip eder:
{"name": "My Token","symbol": "MTK","description": "A description of the token","image": "https://example.com/token-image.png","external_url": "https://example.com","attributes": [{"trait_type": "Category","value": "Utility"}],"properties": {"files": [{"uri": "https://example.com/token-image.png","type": "image/png"}]}}
Metadata JSON'unuzu Arweave, IPFS veya özel bir CDN gibi güvenilir ve kalıcı bir depolama çözümünde saklayın. URI'ye erişilemez hale gelirse, cüzdanlar ve gezginler token'ınızın metadata'sını görüntüleyemez.
Metadata Hesap Yapısı
Zincir üzerindeki metadata hesabı şunları içerir:
pub struct Metadata {pub key: Key, // Account type identifierpub update_authority: Pubkey, // Can update metadatapub mint: Pubkey, // Associated mintpub name: String, // Token name (max 32 chars)pub symbol: String, // Token symbol (max 10 chars)pub uri: String, // URI to off-chain JSON (max 200 chars)pub seller_fee_basis_points: u16, // Royalty % (100 = 1%)pub creators: Option<Vec<Creator>>, // Creator list with sharespub primary_sale_happened: bool, // Primary sale flagpub is_mutable: bool, // Can metadata be updatedpub edition_nonce: Option<u8>, // Edition noncepub token_standard: Option<TokenStandard>, // Token typepub collection: Option<Collection>, // Collection infopub uses: Option<Uses>, // Use tracking}
En İyi Uygulamalar
- Uygun değiştirilebilirlik ayarlayın: Asla değişmemesi gereken token'lar
için
isMutable: falsekullanın - Güvenilir URI barındırma kullanın: Zincir dışı metadata kalıcı depolamada olmalıdır
- Yaratıcıları doğrulayın: Yaratıcı adresleri, özgünlüğü onaylamak için doğrulanmalıdır
- Telif ücretlerini göz önünde bulundurun: İkincil satış telif ücretleri
için
sellerFeeBasisPointsayarlayın (pazaryerleri bunları uygulayabilir veya uygulamayabilir)
Is this page helpful?