الرموز القياسية SPL لا تتضمن بيانات وصفية مثل الاسم أو الرمز أو الصورة. برنامج Metaplex Token Metadata يحل هذه المشكلة من خلال إنشاء حساب بيانات وصفية مرتبط بكل سك رمزي.
يغطي هذا الدليل برنامج Metaplex Token Metadata الذي يمكن استخدامه للرموز القياسية SPL و Token-2022. لاستخدام امتداد البيانات الوصفية Token-2022، راجع دليل امتداد البيانات الوصفية الذي يخزن البيانات الوصفية مباشرة على حساب السك.
كيفية عمل البيانات الوصفية للرموز
ينشئ برنامج البيانات الوصفية للرموز Program Derived Address (PDA) لكل سك رمزي. يخزن حساب البيانات الوصفية هذا معلومات على السلسلة مثل اسم الرمز ورمزه، بالإضافة إلى URI يشير إلى بيانات JSON الوصفية خارج السلسلة (الصور، الأوصاف، إلخ).
┌─────────────────┐ ┌─────────────────────┐│ Mint Account │ │ Metadata Account ││ │ │ (PDA) ││ - Supply │◄──────│ - Name ││ - Decimals │ │ - Symbol ││ - Authority │ │ - URI │└─────────────────┘ │ - Seller Fee ││ - Creators │└─────────────────────┘
يتم اشتقاق PDA للبيانات الوصفية من البذور:
["metadata", program_id, mint_address]
إنشاء رمز مع البيانات الوصفية
تعليمة createV1 تنشئ كلاً من حساب السك وبياناته الوصفية في معاملة واحدة.
تايب سكريبت
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);
جلب البيانات الوصفية للرمز
لمعرفة كيفية جلب البيانات الوصفية للرموز الموجودة، راجع وصفة كتاب الطبخ جلب البيانات الوصفية للرمز.
تحديث البيانات الوصفية للرمز
يمكن لسلطة التحديث تعديل البيانات الوصفية إذا كان الحساب قابلاً للتغيير.
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");
معايير الرموز
يدعم برنامج البيانات الوصفية للرموز معايير مختلفة للرموز:
| المعيار | الوصف | حالة الاستخدام |
|---|---|---|
Fungible | رمز قابل للاستبدال قياسي مع بيانات وصفية | العملات، النقاط |
FungibleAsset | رمز قابل للاستبدال يمثل أصلاً فريداً | عناصر شبه قابلة للاستبدال |
NonFungible | رمز غير قابل للاستبدال مع إصدار رئيسي | عمل فني 1/1 |
ProgrammableNonFungible | رمز غير قابل للاستبدال مع إتاوات مفروضة | إتاوات المبدعين |
NonFungibleEdition | نسخة مطبوعة من رمز غير قابل للاستبدال | إصدارات محدودة |
ProgrammableNonFungibleEdition | نسخة مطبوعة مع إتاوات مفروضة | إصدارات محدودة |
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;
تنسيق البيانات الوصفية خارج السلسلة
يشير حقل uri إلى ملف JSON يحتوي على بيانات وصفية موسعة. يتبع التنسيق القياسي
معيار Metaplex للبيانات الوصفية للرموز:
{"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"}]}}
قم بتخزين ملف JSON للبيانات الوصفية على حل تخزين موثوق ودائم مثل Arweave أو IPFS أو شبكة CDN مخصصة. إذا أصبح عنوان URI غير قابل للوصول، فلن تتمكن المحافظ والمستكشفات من عرض البيانات الوصفية لرمزك.
بنية حساب البيانات الوصفية
يحتوي حساب البيانات الوصفية على السلسلة على:
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}
أفضل الممارسات
- تعيين قابلية التعديل المناسبة: استخدم
isMutable: falseللرموز التي لا يجب أن تتغير أبدًا - استخدام استضافة URI موثوقة: يجب أن تكون البيانات الوصفية خارج السلسلة على تخزين دائم
- التحقق من المنشئين: يجب التحقق من عناوين المنشئين لتأكيد الأصالة
- مراعاة حقوق الملكية: قم بتعيين
sellerFeeBasisPointsلحقوق الملكية من المبيعات الثانوية (قد تقوم الأسواق بفرضها أو لا)
Is this page helpful?