聚焦资讯
服务于区块链创业者

solana(SOL)链上如何使用元数据指针扩展简化了向 Mint 帐户添加元数据的过程

chatGPT账号

在令牌扩展计划和 令牌元数据接口之前,向 Mint 帐户添加额外数据的过程需要通过 Metaplex 元数据计划创建元数据帐户。

MetadataPointer扩展现在允许 Mint 帐户指定其相应元数据帐户的地址。这种灵活性允许铸币帐户指向实现令牌元数据接口的程序所拥有的任何帐户。

令牌扩展程序直接实现令牌元数据接口,可通过TokenMetadata扩展进行访问。通过TokenMetadata 扩展,Mint 帐户本身现在可以存储元数据。

在本指南中,我们将演示如何创建支持MetadataPointerTokenMetadata扩展的 Mint 帐户。此设置通过将所有数据存储在单个帐户上,简化了向 Mint 帐户添加元数据的过程。这是 最终的脚本。

令牌元数据接口概述#

令牌 元数据接口 旨在通过定义用于处理元数据的数据结构和指令集来标准化和简化向令牌添加元数据的过程。

令牌元数据接口可以由任何程序实现。这使开发人员能够灵活地创建自定义元数据程序,同时减少与其程序的生态系统集成相关的挑战。

通过这个通用接口,钱包、dApp 和链上程序可以普遍访问代币元数据,并且用于创建或修改元数据的工具变得普遍兼容。

元数据接口字段#

令牌元数据接口定义了一组标准的数据字段 TokenMetadata,如下所述。此外,它还允许在该部分中包含自定义数据字段additional_metadata,格式为键值对。

pub struct TokenMetadata {
    /// The authority that can sign to update the metadata
    pub update_authority: OptionalNonZeroPubkey,
    /// The associated mint, used to counter spoofing to be sure that metadata
    /// belongs to a particular mint
    pub mint: Pubkey,
    /// The longer name of the token
    pub name: String,
    /// The shortened symbol for the token
    pub symbol: String,
    /// The URI pointing to richer metadata
    pub uri: String,
    /// Any additional metadata about the token as key-value pairs. The program
    /// must avoid storing the same key twice.
    pub additional_metadata: Vec<(String, String)>,
}

元数据接口说明#

元数据接口指定以下 指令:

  • 初始化:初始化基本令牌元数据字段(名称、符号、URI)。
  • UpdateField:更新现有令牌元数据字段或添加到该字段additional_metadata (如果尚不存在)。需要调整帐户大小以容纳额外的空间。
  • RemoveKey:从 .txt 文件中删除键值对additional_metadata。此指令不适用于所需的名称、符号和 URI 字段。
  • UpdateAuthority:更新允许更改令牌元数据的权限。
  • Emit:以结构体的格式发出令牌元数据TokenMetadata。这允许帐户数据以不同的格式存储,同时保持与接口标准的兼容性。

入门#

首先使用 以下起始代码打开此 Solana Playground链接。

// Client
console.log("My address:", pg.wallet.publicKey.toString());
const balance = await pg.connection.getBalance(pg.wallet.publicKey);
console.log(`My balance: ${balance / web3.LAMPORTS_PER_SOL} SOL`);

如果这是您第一次使用 Solana Playground,您首先需要创建一个 Playground 钱包并使用 devnet SOL 为钱包充值。

信息

如果您没有 Playground 钱包,您可能会在编辑器中看到pg.wallet.publicKey. 创建 Playground 钱包后,此类型错误将会清除。

要获取 devnet SOL,请solana airdrop在 Playground 的终端中运行命令,或访问此devnet faucet。

solana airdrop 5

创建并资助 Playground 钱包后,单击“运行”按钮来运行起始代码。

添加依赖项#

让我们从设置脚本开始。我们将使用@solana/web3.js、 @solana/spl-token@solana/spl-token-metadata库。

将起始代码替换为以下内容:

import {
  Connection,
  Keypair,
  SystemProgram,
  Transaction,
  clusterApiUrl,
  sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
  ExtensionType,
  TOKEN_2022_PROGRAM_ID,
  createInitializeMintInstruction,
  getMintLen,
  createInitializeMetadataPointerInstruction,
  getMint,
  getMetadataPointerState,
  getTokenMetadata,
  TYPE_SIZE,
  LENGTH_SIZE,
} from "@solana/spl-token";
import {
  createInitializeInstruction,
  createUpdateFieldInstruction,
  createRemoveKeyInstruction,
  pack,
  TokenMetadata,
} from "@solana/spl-token-metadata";

// Playground wallet
const payer = pg.wallet.keypair;

// Connection to devnet cluster
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

// Transaction to send
let transaction: Transaction;
// Transaction signature returned from sent transaction
let transactionSignature: string;

薄荷设置#

接下来,定义我们将在下一步中创建的 Mint 帐户的属性。

// Generate new keypair for Mint Account
const mintKeypair = Keypair.generate();
// Address for Mint Account
const mint = mintKeypair.publicKey;
// Decimals for Mint Account
const decimals = 2;
// Authority that can mint new tokens
const mintAuthority = pg.wallet.publicKey;
// Authority that can update the metadata pointer and token metadata
const updateAuthority = pg.wallet.publicKey;

// Metadata to store in Mint Account
const metaData: TokenMetadata = {
  updateAuthority: updateAuthority,
  mint: mint,
  name: "OPOS",
  symbol: "OPOS",
  uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json",
  additionalMetadata: [["description", "Only Possible On Solana"]],
};

接下来,确定新铸币账户的大小,并计算免除租金所需的最少 lamports。

在下面的代码片段中,我们为TokenMetadata扩展分配了4个字节,然后计算元数据所需的空间。

// Size of MetadataExtension 2 bytes for type, 2 bytes for length
const metadataExtension = TYPE_SIZE + LENGTH_SIZE;
// Size of metadata
const metadataLen = pack(metaData).length;

// Size of Mint Account with extension
const mintLen = getMintLen([ExtensionType.MetadataPointer]);

// Minimum lamports required for Mint Account
const lamports = await connection.getMinimumBalanceForRentExemption(
  mintLen + metadataExtension + metadataLen,
);

对于令牌扩展,Mint 帐户的大小将根据启用的扩展而有所不同。

构建说明#

接下来,让我们构建一组指令来:

  • 创建一个新账户
  • 初始化MetadataPointer扩展
  • 初始化剩余的Mint账户数据
  • 初始化TokenMetadata扩展和令牌元数据
  • 使用自定义字段更新令牌元数据

首先,构建指令来调用系统程序来创建帐户并将所有权分配给令牌扩展程序。

// Instruction to invoke System Program to create new account
const createAccountInstruction = SystemProgram.createAccount({
  fromPubkey: payer.publicKey, // Account that will transfer lamports to created account
  newAccountPubkey: mint, // Address of the account to create
  space: mintLen, // Amount of bytes to allocate to the created account
  lamports, // Amount of lamports transferred to created account
  programId: TOKEN_2022_PROGRAM_ID, // Program assigned as owner of created account
});

接下来,构建指令来初始化MetadataPointerMint 帐户的扩展。在这个例子中,元数据指针将指向Mint地址,表明元数据将直接存储在Mint账户上。

// Instruction to initialize the MetadataPointer Extension
const initializeMetadataPointerInstruction =
  createInitializeMetadataPointerInstruction(
    mint, // Mint Account address
    updateAuthority, // Authority that can set the metadata address
    mint, // Account address that holds the metadata
    TOKEN_2022_PROGRAM_ID,
  );

接下来,构建指令来初始化 Mint 账户数据的其余部分。这与原始令牌计划相同。

// Instruction to initialize Mint Account data
const initializeMintInstruction = createInitializeMintInstruction(
  mint, // Mint Account Address
  decimals, // Decimals of Mint
  mintAuthority, // Designated Mint Authority
  null, // Optional Freeze Authority
  TOKEN_2022_PROGRAM_ID, // Token Extension Program ID
);

接下来,构建指令来初始化TokenMetadata扩展和所需的元数据字段(名称、符号、URI)。

对于此指令,使用令牌扩展程序作为programId,其功能相当于“元数据程序”。此外,铸币厂账户的地址用作表明metadata铸币厂本身是“元数据账户”。

// Instruction to initialize Metadata Account data
const initializeMetadataInstruction = createInitializeInstruction({
  programId: TOKEN_2022_PROGRAM_ID, // Token Extension Program as Metadata Program
  metadata: mint, // Account address that holds the metadata
  updateAuthority: updateAuthority, // Authority that can update the metadata
  mint: mint, // Mint Account address
  mintAuthority: mintAuthority, // Designated Mint Authority
  name: metaData.name,
  symbol: metaData.symbol,
  uri: metaData.uri,
});

UpdateField接下来,使用令牌元数据接口中的指令构建指令以使用自定义字段更新元数据 。

该指令将更新现有字段的值,或者将其添加到 additional_metadata(如果该字段尚不存在)。请注意,您可能需要为帐户重新分配更多空间以容纳附加数据。在此示例中,我们在创建帐户时预先分配了租金所需的所有 lamport。

// Instruction to update metadata, adding custom field
const updateFieldInstruction = createUpdateFieldInstruction({
  programId: TOKEN_2022_PROGRAM_ID, // Token Extension Program as Metadata Program
  metadata: mint, // Account address that holds the metadata
  updateAuthority: updateAuthority, // Authority that can update the metadata
  field: metaData.additionalMetadata[0][0], // key
  value: metaData.additionalMetadata[0][1], // value
});

发送交易#

接下来,将指令添加到新交易中并将其发送到网络。这将创建一个启用了MetadataPointerTokenMetadata 扩展的 Mint 帐户,并将元数据存储在 Mint 帐户上。

信息

一些令牌扩展指令需要在初始化铸币之前以原子方式排序。而其他人一定在后面。如果这些说明“无序”,可能会导致您的交易失败。

// Add instructions to new transaction
transaction = new Transaction().add(
  createAccountInstruction,
  initializeMetadataPointerInstruction,
  // note: the above instructions are required before initializing the mint
  initializeMintInstruction,
  initializeMetadataInstruction,
  updateFieldInstruction,
);

// Send transaction
transactionSignature = await sendAndConfirmTransaction(
  connection,
  transaction,
  [payer, mintKeypair], // Signers
);

console.log(
  "\nCreate Mint Account:",
  `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
);

从 Mint 帐户读取元数据#

接下来,检查元数据是否已存储在 Mint 帐户中。

首先获取 Mint 帐户并读取MetadataPointer帐户数据的扩展部分:

// Retrieve mint information
const mintInfo = await getMint(
  connection,
  mint,
  "confirmed",
  TOKEN_2022_PROGRAM_ID,
);

// Retrieve and log the metadata pointer state
const metadataPointer = getMetadataPointerState(mintInfo);
console.log("\nMetadata Pointer:", JSON.stringify(metadataPointer, null, 2));

接下来,读取帐户数据的元数据部分:

// Retrieve and log the metadata state
const metadata = await getTokenMetadata(
  connection,
  mint, // Mint Account address
);
console.log("\nMetadata:", JSON.stringify(metadata, null, 2));

单击按钮运行脚本Run。然后您可以在 SolanaFM 上检查交易详细信息。

您还应该看到类似于以下内容的控制台输出:

Metadata Pointer: {
  "authority": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R",
  "metadataAddress": "BFqmKEm12CrDbcFAncjL34Anu5w18LruxQrgvy7aExzV"
}

Metadata: {
  "updateAuthority": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R",
  "mint": "BFqmKEm12CrDbcFAncjL34Anu5w18LruxQrgvy7aExzV",
  "name": "OPOS",
  "symbol": "OPOS",
  "uri": "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json",
  "additionalMetadata": [
    [
      "description",
      "Only Possible On Solana"
    ]
  ]
}

删除自定义字段#

要从元数据中删除自定义字段,请使用RemoveKey令牌元数据接口中的指令。

信息

idempotent标志用于指定如果账户上不存在该密钥,交易是否应该失败。如果幂等标志设置为true,那么即使键不存在,指令也不会出错。

// Instruction to remove a key from the metadata
const removeKeyInstruction = createRemoveKeyInstruction({
  programId: TOKEN_2022_PROGRAM_ID, // Token Extension Program as Metadata Program
  metadata: mint, // Address of the metadata
  updateAuthority: updateAuthority, // Authority that can update the metadata
  key: metaData.additionalMetadata[0][0], // Key to remove from the metadata
  idempotent: true, // If the idempotent flag is set to true, then the instruction will not error if the key does not exist
});

// Add instruction to new transaction
transaction = new Transaction().add(removeKeyInstruction);

// Send transaction
transactionSignature = await sendAndConfirmTransaction(
  connection,
  transaction,
  [payer],
);

console.log(
  "\nRemove Additional Metadata Field:",
  `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
);

// Retrieve and log the metadata state
const updatedMetadata = await getTokenMetadata(
  connection,
  mint, // Mint Account address
);
console.log("\nUpdated Metadata:", JSON.stringify(updatedMetadata, null, 2));

console.log(
  "\nMint Account:",
  `https://solana.fm/address/${mint}?cluster=devnet-solana`,
);

单击按钮运行脚本Run。然后,您可以在 SolanaFM 上检查交易详细信息和铸币账户。

您还应该看到类似于以下内容的控制台输出:

Updated Metadata: {
  "updateAuthority": "Ehqz1TAMboGbY5oBWqKKWmv5hhvQuwcpkaWbVjkU96cZ",
  "mint": "9wdvSnsqgYo4HFBYMtiCvVNQfFBYdzSeACjLuxVCDcjB",
  "name": "OPOS",
  "symbol": "OPOS",
  "uri": "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json",
  "additionalMetadata": []
}

结论#

通过启用MetadataPointerTokenMetadata扩展,Mint 账户现在可以直接存储代币元数据。此功能简化了向 Mint 帐户添加元数据的过程。

pdf+视频Solana链SOL发币教程及多模式组合合约源代码下载:

Solana链SOL发币(合约部署、开源、锁仓、LP、参数配置、开发、故障处理、工具使用)教程下载:

多模式(燃烧、回流指定营销地址、分红本币及任意币种,邀请推广八代收益,LP加池分红、交易分红、复利分红、NFT分红、自动筑池、动态手续费、定时开盘、回购)组合合约源代码下载:

pdf+视频Solana链SOL发币教程及多模式组合合约源代码下载地址:

此内容仅供注册用户可见,请登录!

添加VX或者telegram获取全程线上免费指导

免责声明

发文时比特币价格:$64249

免责声明:

本文不代表行至网立场,且不构成投资建议,请谨慎对待。用户由此造成的损失由用户自行承担,与行至网没有任何关系;

行至网不对网站所发布内容的准确性,真实性等任何方面做任何形式的承诺和保障;

网站内所有涉及到的区块链(衍生)项目,行至网对项目的真实性,准确性等任何方面均不做任何形式的承诺和保障;

网站内所有涉及到的区块链(衍生)项目,行至网不对其构成任何投资建议,用户由此造成的损失由用户自行承担,与行至网没有任何关系;

行至区块链研究院声明:行至区块链研究院内容由行至网发布,部分来源于互联网和行业分析师投稿收录,内容为行至区块链研究院加盟专职分析师独立观点,不代表行至网立场。

chatGPT账号
赞(0) 打赏
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权,未经允许不得转载。
文章名称:《solana(SOL)链上如何使用元数据指针扩展简化了向 Mint 帐户添加元数据的过程》
文章链接:https://www.xingzhi.io/webthree/30146.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

服务于区块链创业者

业务范围商务合作

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的区块链世界!

支付宝扫一扫打赏

微信扫一扫打赏

登录后才能复制或下载网站内容