如何解析Solana SPL代币账户数据 获取代币类型与持有数量
SPL代币账户二进制Blob数据解析方案
SPL代币(含SPL Token、Token-2022标准)的账户数据为固定布局的二进制结构,其中核心字段偏移固定:
- 代币类型(对应代币铸造地址Mint):位于二进制数据0~32字节位置,为32字节长度的Solana公钥
- 代币持有数量:位于二进制数据64~72字节位置,为小端序编码的64位无符号整数,单位是代币的最小分度值
以下是三种常用工具链的可落地方案:
方案1:基于solana-cli实现
快速解析(无需手动处理二进制)
直接调用cli内置的账户解析能力,自动识别SPL代币账户结构,执行命令:
solana account <你的代币账户地址> --output json
返回结果中:
data.parsed.info.mint字段即为代币类型对应的铸造地址data.parsed.info.tokenAmount.amount字段即为最小单位的代币持有数量
手动解析原始二进制
如果需要直接操作原始blob数据,先导出账户原始数据:
solana account <你的代币账户地址> --output json > raw_acc.json
通过命令行工具按偏移切分解析:
# 提取0-32字节转base58格式公钥,得到代币类型 cat raw_acc.json | jq -r '.data[0]' | base64 -d | dd bs=1 skip=0 count=32 2>/dev/null | solana address # 提取64偏移处的8字节,按小端无符号64位整数解析,得到持有数量 cat raw_acc.json | jq -r '.data[0]' | base64 -d | dd bs=1 skip=64 count=8 2>/dev/null | od -An -tu8 --endian=little
方案2:基于@solana/web3.js实现
先安装依赖:
npm install @solana/web3.js @solana/spl-token
官方SDK解析(兼容普通SPL Token和Token-2022)
const { Connection, PublicKey } = require('@solana/web3.js'); const { getAccount, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } = require('@solana/spl-token'); async function getTokenInfo(accountAddress) { // 替换为你自己的Solana节点RPC地址 const connection = new Connection("你的Solana节点RPC地址"); const accountPubkey = new PublicKey(accountAddress); const accountInfo = await connection.getAccountInfo(accountPubkey); let tokenAccount; if (accountInfo.owner.equals(TOKEN_PROGRAM_ID)) { tokenAccount = await getAccount(connection, accountPubkey, "confirmed", TOKEN_PROGRAM_ID); } else if (accountInfo.owner.equals(TOKEN_2022_PROGRAM_ID)) { tokenAccount = await getAccount(connection, accountPubkey, "confirmed", TOKEN_2022_PROGRAM_ID); } else { throw new Error("输入地址不是有效SPL代币账户"); } return { mint: tokenAccount.mint.toBase58(), // 代币类型 amount: tokenAccount.amount // BigInt类型的最小单位持仓量 } }
手动解析原始二进制(无spl-token依赖)
async function parseRawBlob(accountAddress) { const connection = new Connection("你的Solana节点RPC地址"); const accountInfo = await connection.getAccountInfo(new PublicKey(accountAddress)); const rawData = accountInfo.data; // 按偏移截取字段 const mint = new PublicKey(rawData.slice(0, 32)).toBase58(); const amount = rawData.readBigUInt64LE(64); return {mint, amount}; }
方案3:基于solana.py实现
先安装依赖:
pip install solana spl-token
官方SDK解析
from solana.rpc.api import Client from solana.publickey import PublicKey from spl.token.client import Token from spl.token.constants import TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID def get_token_info(account_address: str): # 替换为你自己的Solana节点RPC地址 client = Client("你的Solana节点RPC地址") account_pubkey = PublicKey(account_address) resp = client.get_account_info(account_pubkey, "confirmed") account_owner = resp.value.owner if account_owner == TOKEN_PROGRAM_ID: program_id = TOKEN_PROGRAM_ID elif account_owner == TOKEN_2022_PROGRAM_ID: program_id = TOKEN_2022_PROGRAM_ID else: raise ValueError("输入地址不是有效SPL代币账户") token_client = Token(client, account_pubkey, program_id, None) token_acc = token_client.get_account_info(account_pubkey) return { "mint": str(token_acc.mint), # 代币类型 "amount": token_acc.amount # 最小单位持仓量 }
手动解析原始二进制
import struct from solana.rpc.api import Client from solana.publickey import PublicKey def parse_raw_blob(account_address: str): client = Client("你的Solana节点RPC地址") account_info = client.get_account_info(PublicKey(account_address), "confirmed").value raw_data = account_info.data # 按偏移截取字段 mint = str(PublicKey(raw_data[0:32])) # <Q 表示小端序无符号64位整数 amount = struct.unpack("<Q", raw_data[64:72])[0] return {"mint": mint, "amount": amount}
注意:手动按偏移提取mint和amount的方法对所有SPL标准代币账户(包括带扩展的Token-2022账户)均有效,这两个字段的基础偏移不会随扩展功能改变。如果需要解析委托、冻结权限、转账钩子等其他字段,优先使用官方SDK提供的解析方法,避免自行处理布局逻辑出错。
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

