介绍
与 Solana 上的数据交互可能具有挑战性。帐户和交易数据通常经过编码,这有利于提高效率,但不利于开发人员的理智。

Solana 使用Borsh(用于哈希的二进制对象表示序列化器)进行数据序列化,其中包括序列化和反序列化过程。Borsh 的主要优势之一是其确定性,可确保相同输入的序列化输出一致。
在本教程中,我们将介绍如何反序列化代币帐户中的帐户数据,并返回可利用的可读数据。您将使用代币程序库从 NFT 的铸币地址中分解原始帐户信息的简单示例。
下面介绍如何将原始帐户数据转换为更易读的数据:
转换原始帐户数据
您可以通过克隆我们的 deserialize-account 存储库(此处)来跟踪本教程中的完整代码。
先决条件
以下是本教程的先决条件:
基本 TypeScript 知识
ts-node已安装
一个 RPC
示例存储库
环境设置
克隆示例存储库:
代码
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您想要反序列化数据的 mint。
下面,您将设置主要功能。
您还将使用我们的 Helius RPC URL 设置我们的 Solana 连接,并且您可以在教程中设置将反序列化的 mint。
代码
async function deserializeMint() {
// CONNECTION TO SOLANA USING HELIUS
const rpc = 'https://rpc.helius.xyz/?api-key=';
const connection = new Connection(rpc);
// MINT THAT WE ARE DESERIALIZING
const mint = new PublicKey('6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K');
}
deserializeMint()
确保将上面的 api-key 替换为您自己的 Helius API 密钥。您也可以将本教程中使用的 mint 替换为您自己的示例。
接下来,您将设置一个 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来查看结果。
您应该看到类似以下的结果:
反序列化 solana 帐户数据
在这里进行反序列化的目的是使其具有可读的格式。
作为开发人员,要做到这一点,您必须转到此处的源代码来找到创建它的程序预期提供的布局。
2. 设置账户类型
在此示例中,您想要获取 SPL mint 的 AccountInfo 6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K。
为此,您必须分解Solana 程序库中提供给我们的原始铸币数据和缓冲区布局的类型。了解给定数据的结构是反序列化 Solana 上的任何数据的关键步骤。
运行 ts-node deserialize 查看结果
上图给出了程序定义的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 的帐户数据所需的上述原始 mint 格式和布局。
现在,您可以设置与上述类似的界面和布局。
笔记:
您正在使用我们导入的 PublicKey、u32、u8、publicKey、u64 和 bool。
代码
// Defining RawMint from https://github.com/solana-labs/solana-program-library/blob/48fbb5b7c49ea35848442bba470b89331dea2b2b/token/js/src/state/mint.ts#L31 //
export interface RawMint {
mintAuthorityOption: 1 | 0;
mintAuthority: PublicKey;
supply: bigint;
decimals: number;
isInitialized: boolean;
freezeAuthorityOption: 1 | 0;
freezeAuthority: PublicKey;
}
// Defining Buffer Layout from https://github.com/solana-labs/solana-program-library/blob/48fbb5b7c49ea35848442bba470b89331dea2b2b/token/js/src/state/mint.ts#L31 //
/** Buffer layout for de/serializing a mint */
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导入:MintLayouttypes.ts
代码
import { MintLayout } from "./types";
现在,您只需在我们的反序列化函数中添加一行,就在您获取帐户数据的位置下方:
代码
const deserialize = MintLayout.decode(data)
console.log(deserialize)
这是使用我们的MintLayout来解码函数中返回的数据deserializeMint。
ts-node deserialize您可以从文件夹运行./src,并将获得类似于以下内容的结果:
代码
{
mintAuthorityOption: 1,
mintAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
_bn:
},
supply: 1n,
decimals: 0,
isInitialized: true,
freezeAuthorityOption: 1,
freezeAuthority: PublicKey [PublicKey(5WQAPQ8i8wqHcSWSEkBQ9kqfwRJxxgyZqAtKiwJSW5zT)] {
_bn:
}
}
这绝对更具可读性!您可以通过在下一步中将响应分解为响应中的类型来使其更加整洁。
最后,您仍可以通过调整响应以使其与上面显示的内容一致来清理此处的数据。您可以通过执行以下操作来实现此目的:
代码
// Breaking down the response //
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;
}
// Data returned.
console.log(data);
// Deserialize Data.
const deserialize = MintLayout.decode(data)
// Breaking down the response //
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 帐户数据!您可以将相同的方法应用于其他用例,并使用类似的研究方法来找出给定数据的程序结构。
确保检查您想要从中反序列化数据的程序的来源,并尝试匹配这些方法自行完成此操作。