Solana 开发基础 101 - 在 Solana 上反序列化账户数据

  • Helius
  • 发布于 2023-07-30 21:30
  • 阅读 11

本文详细介绍了如何在Solana网络中反序列化代币账户数据,应用Borsh序列化方法。读者将学习如何设置环境、提取账户信息,以及将原始数据转换为可读格式的步骤,适合对Solana开发有基础的开发者。最后提供完整代码示例和资源链接。

5分钟阅读

2023年7月28日

介绍

在Solana上与数据交互可能具有挑战性。账户和交易数据通常是编码格式,这对于效率有好处,但对开发人员的理解性造成了困扰。

Solana使用Borsh(用于哈希的二进制对象表示序列化器)进行数据序列化,包括序列化和反序列化过程。Borsh的一个关键优势是其确定性,确保相同输入输出一致的序列化结果。

在本教程中,我们将介绍如何反序列化来自代币账户的账户数据,并返回可供使用的可读数据。你将使用从其铸造地址获取NFT的原始账户信息的简单例子,使用代币程序库进行处理。

下面是我们将如何将原始账户数据转换为更易读的东西的说明:

transform raw account data

你可以通过克隆我们的deserialize-account代码库来查看本教程中的完整代码,这里

先决条件

以下是本教程的先决条件:

环境设置

克隆示例代码库:

代码

git clone https://github.com/helius-labs/deserialize-base.git

进入项目目录:

代码

cd deserialize-base

安装npm:

代码

npm install

现在你已经设置好项目了!

你可以开始构建如何反序列化给定铸造地址的账户数据。

构建步骤

按照以下步骤操作:

1. 获取账户数据

在我们的/src/deserialize.ts文件中,导入所需的模块:

代码

import { Connection, PublicKey } from "@solana/web3.js";

你将在后面使用它来定义与Solana的连接,以及要反序列化数据的铸造的PublicKey

在下面,你将设置主函数。

你还将使用我们的Helius RPC URL设置Solana连接,并可以设置你将在教程中反序列化的铸造。

代码

async function deserializeMint() {
        // 连接到Solana使用Helius
    const rpc = 'https://rpc.helius.xyz/?api-key=';
    const connection = new Connection(rpc);
        // 我们要反序列化的铸造
    const mint = new PublicKey('6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K');

}
deserializeMint()

请确保在上述代码中将api-key替换为你自己的Helius API密钥。你还可以用你自己的示例替换用于本教程的铸造。

接下来,你将设置一个try/catch来获取此铸造的原始账户数据:

代码

try {
    let { data } = (await connection.getAccountInfo(mint)) || {};
    if (!data) {
      return;
    }
    console.log(data);
  } catch {
    return null;
  }

在上面的步骤中,你使用我们的连接对Solana进行RPC调用以获取getAccountInfo。这将返回你需要进一步分解的初始数据。

如果没有找到数据,将返回null。否则,它将在你的终端中输出查询结果。

你现在可以运行ts-node deserialize以查看结果。

你应该会看到类似以下的结果:

deserialize solana account data

能够反序列化的目的在于将其转换为可读格式。

作为开发者,你需要进入源代码找到由其创建的程序所期望的布局。

2. 设置账户类型

在本例中,你希望获取SPL铸造6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K的AccountInfo。

为此,你需要分解原始铸造数据和缓冲布局中给出的类型,这些内容可以在Solana程序库中找到。理解给定数据的结构是反序列化任何Solana数据的关键步骤。

run ts-node deserialize to see the results

上面的图像向你介绍了程序定义的RawMint结构和MintLayout。你实际上可以将其复制到我们的类型文件中使用。

现在,前往我们的./src/types目录。

/src/types.ts文件中,设置类型的导入:

代码

import { PublicKey } from "@solana/web3.js";
import { u32, u8, struct } from "@solana/buffer-layout";
import { publicKey, u64, bool } from "@solana/buffer-layout-utils";

这将定义上述原始铸造格式以及反序列化该示例中的NFT账户数据所需的布局。

现在,你可以设置我们的接口和布局,形式类似于上述内容。

注意:

你使用的是导入的PublicKey、u32、u8、publicKey、u64和bool。

代码

// 从https://github.com/solana-labs/solana-program-library/blob/48fbb5b7c49ea35848442bba470b89331dea2b2b/token/js/src/state/mint.ts#L31定义RawMint //
export interface RawMint {
    mintAuthorityOption: 1 | 0;
    mintAuthority: PublicKey;
    supply: bigint;
    decimals: number;
    isInitialized: boolean;
    freezeAuthorityOption: 1 | 0;
    freezeAuthority: PublicKey;
}

// 从https://github.com/solana-labs/solana-program-library/blob/48fbb5b7c49ea35848442bba470b89331dea2b2b/token/js/src/state/mint.ts#L31定义缓冲布局 //

/** 用于反序列化/序列化铸造的流程布局 */
export const MintLayout = struct([\
    u32('mintAuthorityOption'),\
    publicKey('mintAuthority'),\
    u64('supply'),\
    u8('decimals'),\
    bool('isInitialized'),\
    u32('freezeAuthorityOption'),\
    publicKey('freezeAuthority'),\
]);

你现在已经设置了原始账户信息的类型!你可以将其导入我们的主deserialize.ts文件,并使用它来反序列化你之前返回的数据。

注意:

MintLayout中,RawMint被定义为结构体。这本质上是将你设置的接口类型化为由GitHub源定义的布局。

3. 反序列化返回的数据

现在你了解了预期数据的结构,可以设置我们的解码函数,仅需一行代码。你可以返回到src/deserialize.ts文件设置此函数。

首先,在我们的主deserialize.ts文件中,从types.ts文件导入我们的MintLayout

代码

import { MintLayout } from "./types";

现在,你只需在获取账户数据之后的解码函数中添加一行代码:

代码

const deserialize = MintLayout.decode(data)
console.log(deserialize)

这使用我们的MintLayout解码在我们的deserializeMint函数中返回的数据。

你可以在./src文件夹中运行ts-node deserialize,会得到类似以下的结果:

代码

{
  mintAuthorityOption: 1,
  mintAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
    _bn:
  },
  supply: 1n,
  decimals: 0,
  isInitialized: true,
  freezeAuthorityOption: 1,
  freezeAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
    _bn:
  }
}

这确实更易读!你可以通过在下一步中对响应进行分解来使其更加整齐。

最后,你还可以通过调整响应清理这些数据,以显示上述内容。你可以通过以下方式实现这一点:

代码

// 分解响应 //
    console.log(deserialize.mintAuthorityOption)
    console.log(deserialize.mintAuthority.toString())
    console.log(deserialize.decimals)
    console.log(deserialize.isInitialized)
    console.log(deserialize.freezeAuthorityOption)
    console.log(deserialize.freezeAuthority.toString())

在上述代码中,你只需将返回的PublicKeys转换为toString格式。否则,数据可以以接收到的格式返回。由于要求的数据格式是固定的,我们可以提前进行这些设置,返回以下内容:

代码

1
5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT
0
true
1

你可以以任何你喜欢的方式调整这些数据。

这只是将其分解为更易于阅读的格式。

完整代码:

请查看deserialize.ts的完整代码:

代码

import { Connection, PublicKey } from "@solana/web3.js";
import { RawMint, MintLayout } from "./types";

async function deserializeMint() {
  const rpc =
    "https://rpc.helius.xyz/?api-key=";
  const connection = new Connection(rpc);
  const mint = new PublicKey("6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K");

  try {
    let { data } = (await connection.getAccountInfo(mint)) || {};
    if (!data) {
      return;
    }
        // 返回的数据。
    console.log(data);
        // 反序列化数据。
    const deserialize = MintLayout.decode(data)

    // 分解响应 //
    console.log(deserialize.mintAuthorityOption)
    console.log(deserialize.mintAuthority.toString())
    console.log(deserialize.decimals)
    console.log(deserialize.isInitialized)
    console.log(deserialize.freezeAuthorityOption)
    console.log(deserialize.freezeAuthority.toString)

  } catch {
    return null;
  }
}
deserializeMint();

结论

你现在已经反序列化了Solana上的NFT账户数据!你可以将相同的方法应用于其他用例,并使用类似的方法研究给定数据的程序结构。

一定要检查你想要反序列化数据的程序的源代码,并尝试匹配这些方法,以便自行完成此操作。

资源

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

0 条评论

请先 登录 后评论
Helius
Helius
https://www.helius.dev/