Les jetons SPL standards n'incluent pas de métadonnées comme un nom, un symbole ou une image. Le programme Metaplex Token Metadata résout ce problème en créant un compte de métadonnées lié à chaque mint de jeton.
Ce guide couvre le programme Metaplex Token Metadata qui peut être utilisé pour les jetons SPL standards et Token-2022. Pour utiliser l'extension Metadata de Token-2022, consultez le guide Extension Metadata qui stocke les métadonnées directement sur le compte mint.
Fonctionnement des métadonnées de jetons
Le programme Token Metadata crée un Program Derived Address (PDA) pour chaque mint de jeton. Ce compte de métadonnées stocke des informations on-chain comme le nom et le symbole du jeton, ainsi qu'un URI pointant vers des métadonnées JSON off-chain (images, descriptions, etc.).
┌─────────────────┐ ┌─────────────────────┐│ Mint Account │ │ Metadata Account ││ │ │ (PDA) ││ - Supply │◄──────│ - Name ││ - Decimals │ │ - Symbol ││ - Authority │ │ - URI │└─────────────────┘ │ - Seller Fee ││ - Creators │└─────────────────────┘
Le PDA de métadonnées est dérivé des seeds :
["metadata", program_id, mint_address]
Créer un jeton avec métadonnées
L'instruction createV1 crée à la fois le compte mint et ses métadonnées dans
une seule transaction.
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);
Récupérer les métadonnées d'un jeton
Pour apprendre à récupérer les métadonnées de jetons existants, consultez la recette cookbook Récupérer les métadonnées d'un jeton.
Mettre à jour les métadonnées d'un jeton
L'autorité de mise à jour peut modifier les métadonnées si le compte est mutable.
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");
Standards de jetons
Le programme Token Metadata prend en charge différents standards de jetons :
| Standard | Description | Cas d'usage |
|---|---|---|
Fungible | Jeton fongible standard avec métadonnées | Devises, points |
FungibleAsset | Jeton fongible représentant un actif unique | Objets semi-fongibles |
NonFungible | NFT avec Master Edition | Œuvre d'art 1/1 |
ProgrammableNonFungible | NFT avec royalties imposées | Royalties créateurs |
NonFungibleEdition | Copie imprimée d'un NFT | Éditions limitées |
ProgrammableNonFungibleEdition | Copie imprimée avec royalties imposées | Éditions limitées |
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;
Format des métadonnées hors chaîne
Le champ uri pointe vers un fichier JSON contenant des métadonnées étendues.
Le format standard suit le
Standard de métadonnées de jeton 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"}]}}
Stockez votre fichier JSON de métadonnées sur une solution de stockage fiable et permanente comme Arweave, IPFS ou un CDN dédié. Si l'URI devient inaccessible, les portefeuilles et explorateurs ne pourront pas afficher les métadonnées de votre jeton.
Structure du compte de métadonnées
Le compte de métadonnées en chaîne contient :
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}
Bonnes pratiques
- Définir la mutabilité appropriée : Utilisez
isMutable: falsepour les jetons qui ne devraient jamais changer - Utiliser un hébergement URI fiable : Les métadonnées hors chaîne doivent être sur un stockage permanent
- Vérifier les créateurs : Les adresses des créateurs doivent être vérifiées pour confirmer l'authenticité
- Considérer les redevances : Définir
sellerFeeBasisPointspour les redevances sur les ventes secondaires (les places de marché peuvent ou non les appliquer)
Is this page helpful?