Solana - 什么是Metaplex Core以及如何铸造首个Core NFT - Quicknode

  • QuickNode
  • 发布于 2025-01-30 13:42
  • 阅读 16

本篇文章介绍了Metaplex Core,这是Solana上一个新轻量级NFT标准,旨在降低铸造成本并提高组合性。通过Umi JavaScript库,读者能够学习如何创建和管理自己的NFT,包括创建集合资产、铸造资产、查询资产以及转移资产的完整步骤,适合希望在Solana上开展NFT项目的开发者。

概述

Metaplex 最近在 Solana 上宣布了一种新的轻量级 NFT 标准,称为 Metaplex Core。本指南将教你关于 Metaplex Core 的知识,以及它的重要性,以及如何使用 Metaplex Core 和 Umi JavaScript 库铸造你的第一个 NFT。

让我们开始吧!

你将要做什么

编写一个脚本,以使用 Umi JavaScript 库铸造一个 Metaplex Core NFT。

你将需要什么

本指南中使用的依赖项

依赖项 版本
@metaplex-foundation/umi ^0.9.1
@metaplex-foundation/umi-bundle-defaults ^0.9.1
@metaplex-foundation/mpl-core ^0.2.0
@solana/web3.js ^1.91.1
solana cli 1.18.1

让我们开始吧!

什么是 Metaplex Core?

Metaplex Core 是一种轻量级的 Solana NFT 标准,它利用单账户设计。该设计允许更高效的执行、更低的铸造成本和更高的可组合性。原始的 Metaplex 标准构建在 Solana 的 SPL 代币标准之上,这需要多个账户才能铸造 NFT(例如,代币账户、元数据账户和主版本账户)。它们的相关程序必须被调用以铸造 NFT。这不仅可能难以管理,而且成本也可能很高(每次铸造超过 0.02 SOL,相比之下,原为 .0037)并且消耗大量计算资源。更高的计算要求意味着交易失败的可能性可能更大(因为超过计算限制),而且在使用跨程序调用(CPI)与你自己程序中的 NFT 交互时会受到限制。

Core 使用单账户结构和可选附加功能。让我们看一下。Core 账户结构定义如下:

字段 大小(字节) 描述
key 1 账户区分符。
owner 32 资产的拥有者。
update_authority 33 资产的更新权限。
name 4 + length 资产的名称。
uri 4 + length 指向链外数据的资产 URI。
seq 1 + (可选,8) 用于通过压缩进行索引的序列号。

来源:GitHub: MPL Core

除了 Core 账户结构,Core 还支持可选附加功能。插件可以附加到 Core 资产或集合资产,允许插件修改单个资产或整个集合的行为。插件分为三种类型:

  • 拥有者管理的插件:这些插件由资产或集合的拥有者管理。
  • 权限管理的插件:这些插件由资产或集合的权限管理。
  • 永久性:这些插件是永久性的,无法移除。必须在创建时初始化。

以下是 Core 中可用插件的总结:

插件 类型 可用对象 描述
Transfer Delegate 拥有者管理 Core Asset 允许拥有者委托可以转移资产的程序。
Freeze Delegate 拥有者管理 Core Asset 允许拥有者委托可以冻结资产的程序。
Burn Delegate 拥有者管理 Core Asset 允许拥有者委托可以销毁资产的程序。
Royalties 权限管理 Core 或 Collection 为资产设置版税和规则。
Update Delegate 权限管理 Core 或 Collection 允许权限委托可以更新资产的程序。
Attribute 权限管理 Core 或 Collection 存储键值对数据(例如,特征)。
Permanent Transfer Delegate 永久性 Core 或 Collection 允许拥有者委托可以转移资产的程序。
Permanent Freeze Delegate 永久性 Core 或 Collection 允许拥有者委托可以冻结资产的程序。
Permanent Burn Delegate 永久性 Core 或 Collection 允许拥有者委托可以销毁资产的程序。

来源:developers.metaplex.com

让我们尝试铸造一个 Core NFT!

创建一个新项目

mkdir core-demo && cd core-demo && echo > app.ts

安装 Solana Web3 依赖:

yarn init -y
yarn add @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-inscription @solana/web3.js@1

npm init -y
npm install @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-core @solana/web3.js@1

设置本地环境

获取 Core 程序

欢迎使用 Solana Devnet,但为了本指南的快速交易时间,我们将使用 Localnet。要在 Localnet 上使用 Core,我们必须首先在本地网络上部署 Core 程序。为此,我们需要使用 solana program dump 命令。这将有效地从 Solana 的 Devnet 获取 Core 程序并将其存储,以便我们可以在本地网络上部署。

在你的终端中运行以下命令:

solana program dump -u d CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d core.so

这将下载存储在 Devnet 上的 Core 程序可执行文件( 程序 ID:CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d)并保存在你当前的目录中。请注意该文件保存的位置,因为我们稍后将需要它。

导入依赖

在你的项目目录中,打开 app.ts 并导入必要的依赖项:

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import {
    createV1,
    mplCore,
    fetchAssetV1,
    transferV1,
    createCollectionV1,
    getAssetV1GpaBuilder,
    Key,
    updateAuthority,
    pluginAuthorityPair,
    ruleSet
} from '@metaplex-foundation/mpl-core'
import { TransactionBuilderSendAndConfirmOptions, generateSigner, signerIdentity, sol } from '@metaplex-foundation/umi';

我们正在从 Metaplex 库中导入一些方法。我们将在使用它们的过程中详细介绍。

初始化 Umi

接下来,我们将初始化 Umi 并设置我们的签名者和付款者。将以下代码添加到你的 app.ts 文件中:

const umi = createUmi('http://127.0.0.1:8899', 'processed').use(mplCore())

const asset = generateSigner(umi);
const payer = generateSigner(umi);

umi.use(signerIdentity(payer));

const txConfig: TransactionBuilderSendAndConfirmOptions = {
    send: { skipPreflight: true },
    confirm: { commitment: 'processed' },
};

在此代码片段中,我们正在使用本地网络端点初始化 Umi,并设置 processed 触及级别(以允许快速处理时间,作为我们的演示)。我们还为资产和付款者生成了一个签名者。付款者将用于支付交易费用(这是通过使用 umi.use 设置的)。 我们还定义了一个 txConfig 对象,将在我们的交易中传入以设置 skipPreflightcommitment 选项。

创建 NFT 铸造逻辑

创建一个主函数

接下来,我们将创建一个 main 函数,该函数将容纳我们脚本的逻辑。将以下代码添加到 app.ts 文件的 main 函数中:

async function main() {
    // 1. 空投给付款者
    console.log('1. Airdropping to: ', payer.publicKey.toString());
    const airdropAmount = sol(100);
    await umi.rpc.airdrop(umi.identity.publicKey, airdropAmount, txConfig.confirm);

    // 2. 创建一个集合资产

    // 3. 在集合中创建一个资产

    // 4. 按所有者获取资产

    // 5. 按集合获取资产

    // 6. 转移资产

}

main().catch(console.error);

在这里,我们创建了一个包含六个步骤的函数(我们将在下一步中填充这些步骤)。我们预填充的第一步是向付款者账户空投一些 SOL。这是支付交易费用所必需的。

创建一个集合资产

接下来,我们将创建一个集合资产。将以下代码添加到 main 函数的第 2 节中:

    // 2. 创建一个集合资产
    const collectionAddress = generateSigner(umi);
    console.log('2. Creating Collection:', collectionAddress.publicKey.toString());
    const collectionUpdateAuthority = generateSigner(umi);
    const creator1 = generateSigner(umi);
    const creator2 = generateSigner(umi);
    await createCollectionV1(umi, {
        name: 'Quick Collection',                           // 👈 替换此项
        uri: 'https://your.domain.com/collection.json',     // 👈 替换此项
        collection: collectionAddress,
        updateAuthority: collectionUpdateAuthority.publicKey,
        plugins: [\
            pluginAuthorityPair({\
                type: 'Royalties',\
                data: {\
                    basisPoints: 500,\
                    creators: [\
                        {\
                            address: creator1.publicKey,\
                            percentage: 20,\
                        },\
                        {\
                            address: creator2.publicKey,\
                            percentage: 80,\
                        },\
                    ],\
                    ruleSet: ruleSet('None'), // 兼容规则集\
                },\
            }),\
        ],
    }).sendAndConfirm(umi, txConfig);

在这里,我们创建了两个新的签名者( collectionUpdateAuthoritycollectionAddress),尽管权限是可选的(默认是付款者)。然后,我们使用来自 mpl-core 库的 createCollectionV1 方法创建一个新的集合资产。我们传入集合的名称、URI、集合地址和更新权限。

确保用你想要的值更新 nameuri。你可以使用 QuickNode 的 IPFS 服务 上传并托管你的 NFT 图像和元数据。

我们使用 Royalties 插件为集合设置版税。在这个例子中,我们使用两个随机创作者,并将基本点数设置为 500(5%)。Core 资产的一个奇妙特性是,其版税可以在集合级别设置并将适用于集合中的所有资产。这是一种简单管理版税的方式(这意味着我们的 NFT 的冗余更少)。我鼓励你探索 pluginAuthorityPair 方法,以查看可以添加到集合的其他插件/参数对。

然后,我们使用我们的 umi 实例和 txConfig 对象发送并确认交易。

在集合中创建一个资产

现在我们已经有了一个集合,让我们为其铸造一个资产。

    // 3. 在集合中创建一个资产
    await createV1(umi, {
        name: 'Quick Asset #1',                         // 👈 替换此项
        uri: 'https://your.domain.com/asset-id.json',   // 👈 替换此项
        asset: asset,
        collection: collectionAddress.publicKey,
        authority: collectionUpdateAuthority,
    }).sendAndConfirm(umi, txConfig);

这一次,我们使用 createV1 方法创建一个新资产。我们传入资产名称、URI(请确保更新为你自己的)、资产地址、集合地址及集合的更新授权。有几件事情需要注意:

  • 我们不需要为资产设置版税,因为它们是从集合中继承的。
  • 为了将资产铸造到集合中,我们必须将集合的更新权限作为 Signer 对象传递。这是因为更新资产的集合的权限是必需的。

按所有者获取资产

当前,Core 并不支持数字资产标准,因此我们需要使用 getProgramAccounts 来获取资产。Metaplex 包含一个用于构建 GPA 查询的辅助函数 getAssetV1GpaBuilder。将以下代码添加到 main 函数的第 4 和第 5 节中:

    // 4. 按所有者获取资产
    const assetsByOwner = await getAssetV1GpaBuilder(umi)
        .whereField('key', Key.AssetV1)
        .whereField('owner', payer.publicKey)
        .getDeserialized();

    console.log(assetsByOwner);

    // 5. 按集合获取资产
    const assetsByCollection = await getAssetV1GpaBuilder(umi)
        .whereField('key', Key.AssetV1)
        .whereField(
            'updateAuthority',
            updateAuthority('Collection', [collectionAddress.publicKey])
        )
        .getDeserialized();

    console.log(assetsByCollection);

这两个查询非常相似——它们将我们的 umi 实例传递给 getAssetV1GpaBuilder 方法,并将 key 字段设置为 Key.AssetV1(从 mpl-core 导入)。第一个查询根据所有者获取资产,第二个查询根据集合获取资产。第二个查询还将 updateAuthority 字段设置为 updateAuthority('Collection', [collectionAddress.publicKey]) 以通过集合地址进行筛选。

每个查询都应该在控制台上记录一个资产数组。

转移资产

最后,让我们将资产转移到另一个账户中。将以下代码添加到 main 函数的第 6 节中:

    // 6. 转移资产
    const recipient = generateSigner(umi);
    await transferV1(umi, {
        asset: asset.publicKey,
        newOwner: recipient.publicKey,
        collection: collectionAddress.publicKey,
     }).sendAndConfirm(umi, txConfig);

如果你曾经使用过 SPL 代币进行过任何转移,这应该看起来令人兴奋地简单!这是单个账户模型的一个显著优势——无需担心代币账户或代币账户初始化。只需传递新的目的地,并确保你有有效的转移资产的权限 🙌。请注意,对于在集合中的资产,我们需要传递集合地址。

你可以通过添加以下内容验证资产是否已被转移:

    const transferredAsset = await fetchAssetV1(umi, asset.publicKey);
    if (transferredAsset.owner.toString() !== recipient.publicKey.toString()) {
        throw new Error('Transfer failed');
    }

干得好!让我们测试我们的脚本。

运行脚本

要在 localnet 上运行我们的代码,我们需要打开两个终端窗口。在第一个终端中,使用你已经部署的 Core 程序启动 localnet。运行:

solana-test-validator -r --bpf-program CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d core.so

确保用之前使用 solana program dump 下载的文件的正确路径替换 core.so

在 localnet 启动后,在第二个终端运行你的脚本:

ts-node app.ts

你应该在终端中看到每一步的输出!干得好!

如果遇到任何错误,请仔细检查你的代码,并确保已安装正确的依赖项。如果你仍然遇到问题,请随时通过 Discord 与我们联系。

继续练习

想要继续在 Core 上练习吗?以下是一些启发体验的想法:

  • 尝试使用 addPluginV1createPlugin 方法为你的 NFT 添加 FreezeDelegate,以启用无需托管的质押。
  • 然后尝试使用 revokePluginAuthorityV1 从你的 NFT 中移除 FreezeDelegate
  • 使用 burnV1 方法销毁 NFT。
  • 使用 updateV1 方法更新 NFT,或使用 updateCollectionV1 方法更新集合。

准备好启动你的项目了吗?

如果你准备好脱离本地主机,QuickNode 提供了快速部署项目的工具。今天就 开始 免费开发者计划吧!

总结

Metaplex Core 为构建低成本、更具可组合性的 Solana NFT 项目创造了令人兴奋的新机会。你现在可以使用单个账户铸造、转移和管理 NFT。我们期待看到你正在构建的内容。请在 Discord 上给我们留言,告诉我们你正在进行的工作!

我们 ❤️ 反馈!

告诉我们 如果你有任何反馈或请求新主题。我们很乐意听取你的意见。

资源

  • 原文链接: quicknode.com/guides/sol...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。