什么是Solana铭文以及如何开始使用

  • QuickNode
  • 发布于 2025-01-30 11:13
  • 阅读 23

本文介绍了Solana上使用Metaplex刻录数据的过程,包括创建项目、连接到Solana Devnet、生成密钥对,以及使用相关依赖项进行刻录的数据操作。读者可以通过具体步骤,掌握如何在链上创建和获取Inscription,并提供了有关如何关联多个Inscription和修改权限的进一步探索。

概述

如果你仔细观察过你的 NFT 的 metadata,你可能会注意到,metadata URI 和图像并没有实际存储在 Solana 上。相反,它们通常存储在第三方存储服务(例如 Arweave、Shadow 或 IPFS)中,而 URI 存储在 Solana 上。这主要是由于链状态中存储大量数据的存储限制和成本。然而,随着 Bitcoin Ordinals 和 BRC-20 代币的快速增长,一些 Solana 标准开始出现以在链上存储数据。铭文(Inscriptions)是存储图像字节数据(或其他数据)在链上的 Solana 账户。这允许可验证的可变性、程序内交互、动态数据等。

在本指南中,我们将讨论 Metaplex 铭文标准,如何创建它们,以及如何从中获取数据。

你将完成的任务

编写一个脚本,使用 Metaplex 在链上铭刻数据,并从 Solana 的 devnet 获取数据。

你需要的准备

本指南中使用的依赖项

依赖项 版本
@metaplex-foundation/umi ^0.8.10
@metaplex-foundation/umi-bundle-defaults ^0.8.10
@metaplex-foundation/mpl-inscription ^0.8.0
@solana/web3.js ^1.87.6

让我们开始吧!

创建新项目

mkdir inscriptions-demo && cd inscriptions-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 --save @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-inscription @solana/web3.js@1

创建一个 tsconfig.json,启用 .json 导入:

tsc -init --resolveJsonModule true

使用 QuickNode 终端连接到 Solana 集群

要在 Solana 上开发,你需要一个 API 终端来与网络连接。你可以使用公共节点或自行部署和管理基础设施;但是,如果你想要 8 倍更快的响应时间,可以将繁重的工作交给我们。

看看为什么超过 50% 的 Solana 项目选择 QuickNode,并在 这里 注册一个免费账户。我们将使用 Solana Devnet 终端。

复制 HTTP 提供者链接:

创建密钥对

你将需要一个拥有 Devnet SOL 的纸钱包来铸造铭文。如果没有,你可以使用以下命令创建一个:

🔑 生成一个新的纸钱包与 Devnet SOL

创建新钱包

你可以将生成的 secretAUTHORITY 粘贴到你的 app.ts 文件中。此仅用于测试目的——你永远不应将你的私钥提交到公共代码库。

你可以在 QuickNode Multi-Chain Faucet 中获取 Devnet SOL。

导入依赖项

在你选择的代码编辑器中打开 app.ts,并在第 1 行导入以下内容:

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import { Keypair } from "@solana/web3.js";
import { fetchInscriptionMetadata, findInscriptionMetadataPda, findInscriptionShardPda, initialize, mplInscription, writeData, fetchInscription } from '@metaplex-foundation/mpl-inscription';
import { createSignerFromKeypair, generateSigner, signerIdentity } from '@metaplex-foundation/umi';
import { fromWeb3JsKeypair } from "@metaplex-foundation/umi-web3js-adapters";

const secret = [...] // 将此替换为你的私钥;
const AUTHORITY = Keypair.fromSecretKey(new Uint8Array(secret));

这些导入将使我们能够创建一个 Umi 实例,建立与 Solana 的 Devnet 连接,并铸造一个铭文。

定义常量

添加你的 QuickNode 端点并定义一个 AUTHORITY 密钥对。在你的导入下,添加以下内容:

const ENDPOINT = 'https://example.solana-devnet.quiknode.pro/123465/'; // 👈 将此替换为你的 QuickNode 端点

创建你的脚本

让我们开始概述将用于创建铭文的函数。在 app.ts 中添加以下内容:

async function inscribe(endpoint: string, authority: Keypair) {
    // 1. 创建 UMI 实例
    console.log('1. 创建 UMI 实例');

    // 2. 获取必要的账户密钥
    console.log('2. 正在获取必要的账户密钥');

    // 3. 创建铭文
    console.log('3. 正在创建铭文');

    // 4. 获取铭文元数据
    console.log('4. 正在获取铭文元数据');

    // 5. 获取铭文
    console.log('5. 正在获取铭文');
}

inscribe(ENDPOINT, AUTHORITY);

我们的函数还没有任何功能,但我们将随着进展逐步填充它。你应该能够通过运行以下命令来验证一切正常:

ts-node app.ts

我们的日志应该打印到控制台:

inscription % ts-node guide.ts
1. 创建 UMI 实例
2. 正在获取必要的账户密钥
3. 正在创建铭文
4. 正在获取铭文元数据
5. 正在获取铭文

让我们填充这个函数。

创建 UMI 实例

让我们首先创建一个 UMI 实例,这将使我们能够连接到 Solana 的 devnet,并使用 Metaplex 铭文程序。在 app.ts 中添加以下内容:

    // 1. 创建 UMI 实例
    console.log('1. 创建 UMI 实例');
    const umi = createUmi(endpoint).use(mplInscription());
    umi.use(signerIdentity(createSignerFromKeypair(umi, fromWeb3JsKeypair(authority))));

我们正在使用我们的 QuickNode 端点创建一个 UMI 实例,并添加 Metaplex 铭文程序。最后,我们将我们的密钥对添加到 UMI 作为我们的签名者。这将使我们能够签署交易并为我们的铭文提供账户租金。

获取必要的账户密钥

要创建我们的铭文,我们需要传递少数几个账户到 API:

  • 一个将存储我们铭文数据的铭文账户(随机生成)
  • 一个使用分片计数器的铭文分片账户,以防止资源竞争并根据铸造顺序跟踪全局铭文排名(通过字符串字面量“Inscription”和“Shard”、程序 ID 以及一个随机的分片整数(最多 32)进行播种)参见
  • 一个将存储我们铭文元数据的铭文元数据账户(通过字符串字面量“Inscription”、程序 ID 和铭文账户进行播种)参见

在你的 inscribe 函数中添加以下内容:

    // 2. 获取必要的账户密钥
    console.log('2. 正在获取必要的账户密钥');
    const inscriptionAccount = generateSigner(umi);
    const inscriptionShardAccount = findInscriptionShardPda(umi, { shardNumber: Math.floor(Math.random() * 32) });
    const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, {
        inscriptionAccount: inscriptionAccount.publicKey,
    });

我们正在为我们的铭文账户生成一个随机密钥对,并使用铭文账户来获取铭文元数据 PDA。我们还使用 findInscriptionMetadataPda 来查找由我们的随机分片号播种的铭文分片账户的 PDA。

创建铭文

我们将创建并发送一个交易到网络以创建我们的铭文。该交易将包括两个指令:

  • initialize 将创建铭文账户、创建铭文元数据账户、写入我们的铭文元数据,并更新铭文分片计数器 (指令来源
  • writeData 将我们的铭文数据写入铭文账户(指令来源

在你的 inscribe 函数中添加以下内容:

    // 3. 创建铭文
    console.log('3. 正在创建铭文');
    const tx = await initialize(umi, {
        inscriptionAccount,
        inscriptionMetadataAccount,
        inscriptionShardAccount,
    }).add(
        writeData(umi, {
            inscriptionAccount: inscriptionAccount.publicKey,
            inscriptionMetadataAccount,
            value: Buffer.from(
                'QuickNode Inscriptions Guide' // 👈 将此替换为你的铭文数据
            ),
            associatedTag: null,
            offset: 0,
        })
    ).sendAndConfirm(umi, {confirm: {commitment: 'finalized'}});

initialize 指令获取我们的 Umi 实例和我们在步骤 2 中定义的所有三个账户。 writeData 指令不需要分片账户,因为它将在 initialize 步骤中更新(用于跟踪铭文排名)。writeData 指令确实需要 WriteDataInstructionArgs,这包括:

  • value:铭文数据(作为 Uint8Array)。在本例中,我们写入字符串 "QuickNode Inscriptions Guide",但它可以是图像、JSON 或任何其他数据。
  • associatedTag:用于将多个铭文与单一铭文元数据相关联的可选相关标签(例如,图像和 JSON)(请参见关于 initializeAssociatedInscription 指令的下一部分)。
  • offset:写入数据的偏移量。因为我们一次写入所有数据,所以我们可以将偏移量设置为 0,但如果你希望将数据附加到现有铭文,可以将偏移量设置为现有数据的长度。

然后我们发送并确认该交易。我们等待交易被 finalized,以便立即获取铭文元数据和铭文数据。

获取铭文元数据

现在我们铭刻的消息应该存储在链上,让我们验证一下我们的铭文元数据和数据是否正确。首先,让我们看看元数据。在你的 inscribe 函数中添加以下内容:

    // 4. 获取铭文元数据
    console.log('4. 正在获取铭文元数据');
    const inscriptionMetadata = await fetchInscriptionMetadata(umi, inscriptionMetadataAccount);
    console.log("   Inscription", inscriptionAccount.publicKey.toString());
    console.log("   Inscription Metadata", inscriptionMetadataAccount[0].toString());
    console.log("   Inscription number: ", inscriptionMetadata.inscriptionRank.toString());

我们只需使用 fetchInscriptionMetadata 函数获取并解码我们的铭文元数据。然后,我们解析返回的数据以显示我们的铭文账户地址、铭文元数据账户地址和铭文排名。

获取铭文数据

现在,令人兴奋的部分。让我们获取我们的铭文数据。在你的 inscribe 函数中添加以下内容:

    // 5. 获取铭文
    console.log('5. 正在获取铭文');
    const inscription = await fetchInscription(umi, inscriptionAccount.publicKey);
    const text = Buffer.from(inscription).toString('utf8');
    console.log("   Inscription Data:",text);

同样,我们使用来自 Metaplex 铭文 API 的函数 fetchInscription 来获取和解码我们的铭文数据。然后我们将数据转换为字符串,并将其记录到控制台。

运行脚本

仔细检查你的工作,确保在你的代码编辑器中没有错误。纠正任何错误,然后你就可以创建你的第一个铭文!

在你的终端中运行你的脚本:

ts-node app.ts

你应该看到以下输出:

inscription % ts-node guide.ts
1. 正在建立与集群的连接
2. 如果需要,正在向 devnet 进行 SOL 空投
3. 正在获取必要的账户密钥
4. 正在创建铭文
5. 正在获取铭文元数据
   Inscription DgHhQJ93pQ6srkY6gB2mnixZFBQ8d5EzQ22yS562kNu9
   Inscription Metadata 6nJngcmYNpPxohcgswRcY4xu8XNDWWEcrcr2BmcHGevv,255
   Inscription number:  5161
6. 正在获取铭文
   Inscription Data: QuickNode Inscriptions Guide

干得不错!你已经使用 Metaplex 铭文标准在 Solana Devnet 上铭刻了一些数据。

进一步探索

铭文程序有几个额外的指令值得探索。

铭刻现有 NFT

如果你想要用数据铭刻现有的 NFT,可以使用 initializeFromMint 指令。该指令将创建一个铭文账户、创建铭文元数据账户、写入我们的铭文元数据,并更新分片计数器。这只能由 token_metadata.update_authority 执行。与 initialize 指令的几个显著区别:

  • initialize 不同,initializeFromMint 指令要求 inscriptionAccount 是一个通过铸造账户播种的 PDA 参见
  • 该指令要求传递 mintAccounttokenMetadataAccount
    // 3. 创建铭文
    console.log('3. 正在创建铭文');
    const tx = await initializeFromMint(umi, {
        mintInscriptionAccount: inscriptionAccount,
        metadataAccount: inscriptionMetadataAccount,
        mintAccount: mint.publicKey,
        tokenMetadataAccount, // 来自 token metadata 的元数据账户
        inscriptionShardAccount, // 用于并发处理
    }).add(
        writeData(umi, {
            inscriptionAccount,
            metadataAccount: inscriptionMetadataAccount,
            value: Buffer.from(
                JSON.stringify(metadata) // 要铭刻的你的 NFT 的元数据
            ),
            associatedTag: null,
            offset: 0,
        })
    ).sendAndConfirm(umi, {confirm: {commitment: 'finalized'}});

关联多个铭文

铭文程序允许你将数据写入多个铭文账户,并将它们与单一的铭文元数据账户相关联。如果你想要为单一 NFT 存储多个数据(例如,图像和 json),这会很有用。

  // ...(首先使用 .initialize() 初始化铭文和铭文元数据账户,如我们之前所做的)

  const associatedInscriptionAccount = findAssociatedInscriptionPda(umi, {
    associated_tag: 'image',
    inscriptionMetadataAccount,
  });

  // 创建一个关联铭文账户。
  await initializeAssociatedInscription(umi, {
    inscriptionAccount: inscriptionAccount.publicKey,
    associationTag: 'image',
  }).sendAndConfirm(umi);

  // 将图像数据写入关联铭文账户
  await writeData(umi, {
    inscriptionAccount: associatedInscriptionAccount,
    inscriptionMetadataAccount,
    value: imageBuffer,
    associatedTag: 'image',
    offset: i,
  }).sendAndConfirm(umi)

清除数据

如果你希望,可以从铭文账户中移除所有数据。这只能由铭文元数据中定义的某个授权进行。注意:如果铭文已经被雕刻(未来的功能),则无法使用此功能。清除数据将删除所有现有数据并将其大小调整为 0。

await clearData(umi, {
  inscriptionAccount: inscriptionAccount.publicKey,
  inscriptionMetadataAccount,
  associatedTag: null, // 在此使用创建时使用的相同标签
})

更改授权

API 包括两个函数,用于更新铭文元数据账户的授权:addAuthorityremoveAuthority。两者都必须由现有授权签署,并要求 inscriptionMetadataAccountaddAuthority 函数要求你传递 newAuthority 以添加。removeAuthority 函数允许删除一个可选的 authority——如果没有传递,则签署授权将从铭文元数据账户中移除。

示例:

await addAuthority(umi, {
  inscriptionMetadataAccount,
  newAuthority: authority.publicKey,
}).sendAndConfirm(umi)

await removeAuthority(umi, {
  inscriptionMetadataAccount,
}).sendAndConfirm(umi)

关闭

你可以关闭一个铭文账户(类似于销毁一个代币)。这将关闭账户并将租金返回给授权者。

await close(umi, {
  inscriptionAccount: inscriptionAccount.publicKey,
  inscriptionMetadataAccount,
})

总结

你现在已准备好开始在 Solana 上铭刻数据!你可以使用 Metaplex 铭文 API 创建铭文、从铭文中获取数据等等。你正在构建什么?加入我们 Discord 并告诉我们!遇到问题?在我们的 Discord 上提问。关注我们的 Twitter 获取新闻和更新。

我们 ❤️ 反馈!

让我们知道 如果你有任何反馈或新的主题请求。我们很想听到你的声音。

资源

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

0 条评论

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