本篇文章介绍了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 是一种轻量级的 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) | 用于通过压缩进行索引的序列号。 |
除了 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 | 允许拥有者委托可以销毁资产的程序。 |
让我们尝试铸造一个 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
欢迎使用 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 并设置我们的签名者和付款者。将以下代码添加到你的 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 对象,将在我们的交易中传入以设置 skipPreflight 和 commitment 选项。
接下来,我们将创建一个 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);
在这里,我们创建了两个新的签名者( collectionUpdateAuthority 和 collectionAddress),尽管权限是可选的(默认是付款者)。然后,我们使用来自 mpl-core 库的 createCollectionV1 方法创建一个新的集合资产。我们传入集合的名称、URI、集合地址和更新权限。
确保用你想要的值更新 name 和 uri。你可以使用 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(请确保更新为你自己的)、资产地址、集合地址及集合的更新授权。有几件事情需要注意:
当前,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 上练习吗?以下是一些启发体验的想法:
addPluginV1 和 createPlugin 方法为你的 NFT 添加 FreezeDelegate,以启用无需托管的质押。revokePluginAuthorityV1 从你的 NFT 中移除 FreezeDelegate。burnV1 方法销毁 NFT。updateV1 方法更新 NFT,或使用 updateCollectionV1 方法更新集合。如果你准备好脱离本地主机,QuickNode 提供了快速部署项目的工具。今天就 开始 免费开发者计划吧!
Metaplex Core 为构建低成本、更具可组合性的 Solana NFT 项目创造了令人兴奋的新机会。你现在可以使用单个账户铸造、转移和管理 NFT。我们期待看到你正在构建的内容。请在 Discord 上给我们留言,告诉我们你正在进行的工作!
告诉我们 如果你有任何反馈或请求新主题。我们很乐意听取你的意见。
- 原文链接: quicknode.com/guides/sol...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!