Метаданные Metaplex

Стандартные SPL-токены не включают метаданные, такие как название, символ или изображение. Программа Metaplex Token Metadata решает эту проблему, создавая аккаунт метаданных, связанный с каждым mint account токена.

Это руководство охватывает программу Metaplex Token Metadata, которая может использоваться для стандартных SPL-токенов и Token-2022. Для использования расширения Metadata Extension в Token-2022 см. руководство по Metadata Extension, которое хранит метаданные непосредственно на аккаунте mint.

Как работают метаданные токенов

Программа Token Metadata создает Program Derived Address (PDA) для каждого mint account токена. Этот аккаунт метаданных хранит on-chain информацию, такую как название токена и символ, а также URI, указывающий на off-chain метаданные в формате JSON (изображения, описания и т.д.).

┌─────────────────┐ ┌─────────────────────┐
│ Mint Account │ │ Metadata Account │
│ │ │ (PDA) │
│ - Supply │◄──────│ - Name │
│ - Decimals │ │ - Symbol │
│ - Authority │ │ - URI │
└─────────────────┘ │ - Seller Fee │
│ - Creators │
└─────────────────────┘

PDA метаданных выводится из seeds: ["metadata", program_id, mint_address]

Создание токена с метаданными

Инструкция createV1 создает как аккаунт mint, так и его метаданные в одной транзакции.

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 connection
const rpc = createSolanaRpc("http://127.0.0.1:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");
// Generate keypairs
const payer = await generateKeyPairSigner();
const mint = await generateKeyPairSigner();
// Fund payer
await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: payer.address,
lamports: lamports(1_000_000_000n),
commitment: "confirmed"
});
// Create fungible token with metadata
const 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 transaction
const { 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);

Получение метаданных токена

Чтобы узнать, как получить метаданные для существующих токенов, см. рецепт в кулинарной книге Fetch Token Metadata.

Обновление метаданных токена

Update authority может изменять метаданные, если аккаунт является изменяемым.

Kit
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 authority
const mintAddress = "YOUR_MINT_ADDRESS";
// Fetch current metadata to preserve existing values
const [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 signer
payer: 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 transaction
const { 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 Metadata поддерживает различные стандарты токенов:

СтандартОписаниеСценарий использования
FungibleСтандартный взаимозаменяемый токен с метаданнымиВалюты, баллы
FungibleAssetВзаимозаменяемый токен, представляющий уникальный активПолувзаимозаменяемые предметы
NonFungibleNFT с Master EditionУникальные произведения искусства
ProgrammableNonFungibleNFT с принудительными роялтиРоялти для создателей
NonFungibleEditionНапечатанная копия NFTОграниченные тиражи
ProgrammableNonFungibleEditionНапечатанная копия с принудительными роялтиОграниченные тиражи
import { TokenStandard } from "@metaplex-foundation/mpl-token-metadata-kit";
// For fungible tokens
tokenStandard: TokenStandard.Fungible;
// For NFTs
tokenStandard: TokenStandard.NonFungible;
// For programmable NFTs (enforced royalties)
tokenStandard: TokenStandard.ProgrammableNonFungible;

Формат метаданных вне блокчейна

Поле uri указывает на JSON-файл, содержащий расширенные метаданные. Стандартный формат соответствует стандарту метаданных токенов Metaplex:

token-metadata.json
{
"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 identifier
pub update_authority: Pubkey, // Can update metadata
pub mint: Pubkey, // Associated mint
pub 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 shares
pub primary_sale_happened: bool, // Primary sale flag
pub is_mutable: bool, // Can metadata be updated
pub edition_nonce: Option<u8>, // Edition nonce
pub token_standard: Option<TokenStandard>, // Token type
pub collection: Option<Collection>, // Collection info
pub uses: Option<Uses>, // Use tracking
}

Рекомендации

  1. Установите соответствующую изменяемость: Используйте isMutable: false для токенов, которые никогда не должны изменяться
  2. Используйте надёжный хостинг URI: Метаданные вне блокчейна должны находиться в постоянном хранилище
  3. Проверяйте создателей: Адреса создателей должны быть верифицированы для подтверждения подлинности
  4. Учитывайте роялти: Установите sellerFeeBasisPoints для роялти от вторичных продаж (маркетплейсы могут применять или не применять их)

Is this page helpful?

Управляется

© 2026 Solana Foundation.
Все права защищены.
Связаться с нами