从网络读取数据
通过获取不同的账户,从 Solana 网络读取数据。本节将帮助您了解 Solana 账户 的结构。每个 Solana 账户都有一个唯一的 地址,用于定位其对应的链上数据。账户包含 状态数据或可执行程序。
获取钱包账户
钱包是由 System Program 拥有的账户。钱包主要用于持有 SOL 并签署交易。当 SOL 第一次发送到一个新地址时,会自动创建一个系统账户。
下面的示例生成一个 新 keypair,请求 SOL 为新的公钥地址提供资金,并检索新资助钱包的账户数据。
import { Keypair, Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";const keypair = Keypair.generate();console.log(`Public Key: ${keypair.publicKey}`);const connection = new Connection("http://localhost:8899", "confirmed");// Funding an address with SOL automatically creates an accountconst signature = await connection.requestAirdrop(keypair.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(signature, "confirmed");const accountInfo = await connection.getAccountInfo(keypair.publicKey);console.log(JSON.stringify(accountInfo, null, 2));
当您获取一个钱包账户时,响应中会包含示例输出右侧显示的字段。
data 字段包含账户的数据,以字节形式存储。对于钱包账户,此字段为空(0 字节)。
executable 字段指示账户的 data
字段是否包含可执行程序代码。对于钱包账户,此字段为 false。
lamports 字段包含账户的 SOL 余额,以
lamports 为单位。
owner 字段显示了拥有该账户的程序。对于钱包账户,所有者始终是 System
Program,其地址为 11111111111111111111111111111111。
rentEpoch
字段是一个遗留字段,来自已弃用的租金机制。(此字段包含在内是为了向后兼容。)
space 字段显示了 data 字段中包含的字节数。这不是
账户类型 本身的字段,但包含在响应中。
在此示例中,space 字段为 0,因为 data 字段包含 0 字节的数据。
获取 Token Program
下面的示例获取了 Token Program,以演示钱包账户和程序账户之间的区别。程序账户存储了 Token Program 的 源代码 的已编译字节码。您可以在 Solana Explorer 上查看此程序账户。
import { Connection, PublicKey } from "@solana/web3.js";const connection = new Connection("https://api.mainnet-beta.solana.com","confirmed");const address = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");const accountInfo = await connection.getAccountInfo(address);
Token Program 是一个可执行程序账户。程序与所有 账户 具有相同的基础字段,但存在关键差异。
{"data": {"type": "Buffer","data": [127, "...truncated, total bytes: 134080...", 0]},"executable": true,"lamports": 4522329612,"owner": "BPFLoader2111111111111111111111111111111111","rentEpoch": 18446744073709552000,"space": 134080}
executable 字段被设置为 true,这表明账户的 data 字段包含可执行代码。
{"data": {"type": "Buffer","data": [127, "...truncated, total bytes: 134080...", 0]},"executable": true,"lamports": 4522329612,"owner": "BPFLoader2111111111111111111111111111111111","rentEpoch": 18446744073709552000,"space": 134080}
data 字段存储程序的可执行代码。
{"data": {"type": "Buffer","data": [127, "...truncated, total bytes: 134080...", 0]},"executable": true,"lamports": 4522329612,"owner": "BPFLoader2111111111111111111111111111111111","rentEpoch": 18446744073709552000,"space": 134080}
每个 program account 都由其
loader program 拥有。在此示例中, owner
是 BPFLoader2 程序。
{"data": {"type": "Buffer","data": [127, "...truncated, total bytes: 134080...", 0]},"executable": true,"lamports": 4522329612,"owner": "BPFLoader2111111111111111111111111111111111","rentEpoch": 18446744073709552000,"space": 134080}
获取 mint account
mint account 是由 Token Program 拥有的账户,存储特定代币的全局元数据。这包括总供应量、小数位数,以及被授权铸造或冻结代币的账户。mint account 的地址在 Solana 网络上唯一标识一个代币。
以下示例获取 USD Coin 的 mint account,以演示程序的状态如何存储在单独的账户中。
import { Connection, PublicKey } from "@solana/web3.js";const connection = new Connection("https://api.mainnet-beta.solana.com","confirmed");const address = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");const accountInfo = await connection.getAccountInfo(address);
Mint account 存储的是状态,而不是可执行代码。它们由 Token Program 拥有,Token Program 包括定义如何创建和更新 mint account 的指令。
{"data": {"type": "Buffer","data": [1, "...truncated, total bytes: 82...", 103]},"executable": false,"lamports": 407438077149,"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA","rentEpoch": 18446744073709552000,"space": 82}
mint account 的 data 字段存储的是状态,而不是可执行代码,因此 executable
字段为 false。
Token Program 定义了 Mint 数据类型,该类型存储在 data 字段中。
data 字段包含序列化的 Mint 账户状态,例如铸币权限、总供应量、小数位数。
要从 Mint 账户中读取数据,必须将 data 字段反序列化为 Mint
数据类型,具体示例请参见 下一个示例。
Mint 账户由 Token Program
拥有。这意味着其 data 字段只能通过 Token Program 的指令进行修改。
反序列化 Mint 账户
在账户的 data
字段中的原始字节可以被有意义地解释之前,必须先进行反序列化。适当的数据类型由拥有该账户的程序定义。大多数 Solana 程序提供客户端库,其中包含抽象反序列化过程的辅助函数。这些函数将原始账户字节转换为结构化数据类型,从而更容易处理账户数据。
例如,@solana/spl-token 库包含 getMint()
函数,用于帮助将 Mint 账户的 data 字段反序列化为
Mint
数据类型,该数据类型由 Token Program 定义。
import { PublicKey, Connection } from "@solana/web3.js";import { getMint } from "@solana/spl-token";const connection = new Connection("https://api.mainnet-beta.solana.com","confirmed");const address = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");const mintData = await getMint(connection, address, "confirmed");
pub struct Mint {/// Optional authority used to mint new tokens. The mint authority may only/// be provided during mint creation. If no mint authority is present/// then the mint has a fixed supply and no further tokens may be/// minted.pub mint_authority: COption<Pubkey>,/// Total supply of tokens.pub supply: u64,/// Number of base 10 digits to the right of the decimal place.pub decimals: u8,/// Is `true` if this structure has been initializedpub is_initialized: bool,/// Optional authority to freeze token accounts.pub freeze_authority: COption<Pubkey>,}
getMint() 函数将 Mint 账户的 data 字段反序列化为 Mint 账户类型。
{"data": {"type": "Buffer","data": [1, "...truncated, total bytes: 82...", 103]},"executable": false,"lamports": 407438077149,"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA","rentEpoch": 18446744073709552000,"space": 82}
您可以在 Solana Explorer 上查看完全反序列化的 mint account 数据。
address 字段包含 mint account 的地址。
mintAuthority 字段显示了唯一可以创建新代币单位的账户。
supply
字段显示了已铸造的代币总数。此值以代币的最小单位表示。要以标准单位获取总供应量,请根据
decimals 字段调整 supply 的值。
decimals 字段显示了代币的小数位数。
isInitialized 字段指示 mint account 是否已初始化。此字段是 Token
Program 中用于安全检查的。
freezeAuthority
字段显示了有权冻结代币账户的账户。被冻结的代币账户无法转移或销毁其包含的代币。
tlvData 字段包含 Token Extensions 的额外数据,需要进一步反序列化。此字段仅与由
Token Extension Program (Token2022) 创建的账户相关。
Is this page helpful?