本文详细介绍了如何在Solana网络中反序列化代币账户数据,应用Borsh序列化方法。读者将学习如何设置环境、提取账户信息,以及将原始数据转换为可读格式的步骤,适合对Solana开发有基础的开发者。最后提供完整代码示例和资源链接。
5分钟阅读
2023年7月28日
在Solana上与数据交互可能具有挑战性。账户和交易数据通常是编码格式,这对于效率有好处,但对开发人员的理解性造成了困扰。
Solana使用Borsh(用于哈希的二进制对象表示序列化器)进行数据序列化,包括序列化和反序列化过程。Borsh的一个关键优势是其确定性,确保相同输入输出一致的序列化结果。
在本教程中,我们将介绍如何反序列化来自代币账户的账户数据,并返回可供使用的可读数据。你将使用从其铸造地址获取NFT的原始账户信息的简单例子,使用代币程序库进行处理。
下面是我们将如何将原始账户数据转换为更易读的东西的说明:
你可以通过克隆我们的deserialize-account代码库来查看本教程中的完整代码,这里。
以下是本教程的先决条件:
克隆示例代码库:
代码
git clone https://github.com/helius-labs/deserialize-base.git
进入项目目录:
代码
cd deserialize-base
安装npm:
代码
npm install
现在你已经设置好项目了!
你可以开始构建如何反序列化给定铸造地址的账户数据。
按照以下步骤操作:
在我们的/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
以查看结果。
你应该会看到类似以下的结果:
能够反序列化的目的在于将其转换为可读格式。
作为开发者,你需要进入源代码找到由其创建的程序所期望的布局。
在本例中,你希望获取SPL铸造6MWfAt3S9Xu4ybxxgPm6e4LSwuXfyAwGXd5yfUqpox9K
的AccountInfo。
为此,你需要分解原始铸造数据和缓冲布局中给出的类型,这些内容可以在Solana程序库中找到。理解给定数据的结构是反序列化任何Solana数据的关键步骤。
上面的图像向你介绍了程序定义的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源定义的布局。
现在你了解了预期数据的结构,可以设置我们的解码函数,仅需一行代码。你可以返回到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 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!