原文作者:PaperMoon团队
基于 Polkadot SDK 构建的区块链,其所有数据本质上都存储在链上的 Key-Value 数据库(键值数据库) 中。
任何外部应用(前端、后端服务、数据分析程序、机器人等)都可以通过 RPC 接口读取这些链上数据。
所谓 On-Chain State(链上状态),指的是运行时(Runtime)所管理的所有状态数据,包括:
• 账户余额(Account Balance)
• 资产信息(Assets Metadata)
• 治理提案(Governance Proposals)
• 质押与验证人信息(Staking State)
• 以及 Runtime 维护的任意业务数据
本文将基于官方示例,讲解如何通过 SDK 查询这些数据,并提供可直接运行的完整代码。
支持的链上查询 SDK
Polkadot 生态提供多种语言 SDK 来访问链上存储:
| SDK | 语言 | 特点 |
|---|---|---|
| PAPI (Polkadot API) | TypeScript | 最新、类型安全、官方推荐 |
| Polkadot.js API | JavaScript | 最常用,但已进入维护模式 |
| Dedot | TypeScript | 轻量、高性能 |
| Python Substrate Interface | Python | 适合数据分析与脚本 |
| Subxt | Rust | 编译期类型安全、性能最佳 |
⚠️ 注意
Polkadot.js API 已不再主动开发,新项目建议使用 PAPI 或 Dedot。
链上数据查询原理
链上状态查询架构图
本地程序
↓
SDK (Polkadot.js / PAPI)
↓
WebSocket RPC
↓
Polkadot 节点
↓
Runtime Storage (Key-Value)
核心流程:
1. 本地程序连接节点 RPC
2. SDK 构造存储查询
3. 节点读取 Runtime Storage
4. 返回 SCALE 编码数据
5. SDK 解码并输出
环境准备(Prerequisites)
请先安装:
• Node.js v18 或更高
• npm / pnpm / yarn
创建项目
mkdir pjs-query-example && cd pjs-query-example && \
npm init -y && npm pkg set type=module
安装依赖
npm install @polkadot/api
查询账户余额(Query Account Balance)
我们将读取 Runtime 存储中的:
System.Account
这是 Substrate 最基础的账户状态存储。
1)创建脚本
创建文件:
query-balance.js
并写入代码:
import { ApiPromise, WsProvider } from '@polkadot/api';
const ASSET_HUB_RPC = 'INSERT_WS_ENDPOINT';
// 示例地址(Polkadot Hub 地址)
const ADDRESS = 'INSERT_ADDRESS';
async function main() {
// 创建 WebSocket Provider
const wsProvider = new WsProvider(ASSET_HUB_RPC);
// 初始化 API
const api = await ApiPromise.create({ provider: wsProvider });
console.log('Connected to Polkadot Hub');
console.log(`Querying balance for: ${ADDRESS}\n`);
// 查询 system.account 存储
const accountInfo = await api.query.system.account(ADDRESS);
// 解构余额信息
const { nonce, data } = accountInfo;
const { free, reserved, frozen } = data;
console.log('Account Information:');
console.log(` Nonce: ${nonce.toString()}`);
console.log(` Free Balance: ${free.toString()}`);
console.log(` Reserved: ${reserved.toString()}`);
console.log(` Frozen: ${frozen.toString()}`);
// 断开连接
await api.disconnect();
}
main().catch(console.error);
2)配置 RPC 节点
将:
INSERT_WS_ENDPOINT
替换为:
wss://polkadot-asset-hub-rpc.polkadot.io
将:
INSERT_ADDRESS
替换为你要查询的钱包地址。
3)运行脚本
node query-balance.js
4)示例输出
Connected to Polkadot Hub
Querying balance for: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3
Account Information:
Nonce: 0
Free Balance: 0
Reserved: 0
Frozen: 0
| 字段 | 含义 |
|---|---|
| nonce | 交易序号(防重放) |
| free | 可用余额 |
| reserved | 保留余额(锁仓) |
| frozen | 冻结余额(治理/质押锁定) |
查询资产信息(Query Asset Information)
现在我们读取 Assets Pallet 的存储,查询:
Polkadot Hub 上的 USDT(资产 ID:1984)
1)创建脚本
创建:
query-asset.js
代码:
import { ApiPromise, WsProvider } from '@polkadot/api';
const ASSET_HUB_RPC = 'INSERT_WS_ENDPOINT';
// USDT 资产 ID
const USDT_ASSET_ID = 1984;
// 查询地址
const ADDRESS = 'INSERT_ADDRESS';
async function main() {
const wsProvider = new WsProvider(ASSET_HUB_RPC);
const api = await ApiPromise.create({ provider: wsProvider });
console.log('Connected to Polkadot Hub');
console.log(`Querying asset ID: ${USDT_ASSET_ID}\n`);
// 查询资产元数据
const assetMetadata = await api.query.assets.metadata(USDT_ASSET_ID);
console.log('Asset Metadata:');
console.log(` Name: ${assetMetadata.name.toUtf8()}`);
console.log(` Symbol: ${assetMetadata.symbol.toUtf8()}`);
console.log(` Decimals: ${assetMetadata.decimals.toString()}`);
// 查询资产详情
const assetDetails = await api.query.assets.asset(USDT_ASSET_ID);
if (assetDetails.isSome) {
const details = assetDetails.unwrap();
console.log('\nAsset Details:');
console.log(` Owner: ${details.owner.toString()}`);
console.log(` Supply: ${details.supply.toString()}`);
console.log(` Accounts: ${details.accounts.toString()}`);
console.log(` Min Balance: ${details.minBalance.toString()}`);
console.log(` Status: ${details.status.type}`);
}
// 查询账户资产余额
console.log(`\nQuerying asset balance for: ${ADDRESS}`);
const assetAccount = await api.query.assets.account(USDT_ASSET_ID, ADDRESS);
if (assetAccount.isSome) {
const account = assetAccount.unwrap();
console.log('\nAsset Account:');
console.log(` Balance: ${account.balance.toString()}`);
console.log(` Status: ${account.status.type}`);
} else {
console.log('\nNo asset balance found for this account');
}
await api.disconnect();
}
main().catch(console.error);
2)运行
node query-asset.js
3)示例输出
Connected to Polkadot Hub
Querying asset ID: 1984
Asset Metadata:
Name: Tether USD
Symbol: USDT
Decimals: 6
Asset Details:
Owner: 15uPcYeUE2XaMiMJuR6W7QGW2LsLdKXX7F3PxKG8gcizPh3X
Supply: 77998622834581
Accounts: 13544
Min Balance: 10000
Status: Live
Querying asset balance for: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3
No asset balance found for this account
| 字段 | 含义 |
|---|---|
| metadata | 资产名称、符号、小数位 |
| owner | 资产管理员 |
| supply | 总发行量 |
| accounts | 持币地址数 |
| minBalance | 最小持仓 |
| status | 是否启用 |
| account.balance | 地址持仓 |
重要补充理解
你刚才做的,其实就是直接读取区块链的 Runtime Storage,而不是调用合约。
这与 EVM 世界差异非常大:
| Ethereum | Polkadot |
|---|---|
| 大多数数据在合约 | 大多数数据在 Runtime Storage |
| 必须调用合约 | 可直接读取链存储 |
| RPC 主要用于交易 | RPC 同时用于数据查询 |
因此,Polkadot 是“可查询型链”,不是纯交易型链。
这也是为什么区块浏览器(Subscan、Polkadot.js Apps)能实时展示几乎所有链上数据 —— 本质上它们就是在做同样的存储查询。
下一步你可以做的:
• 做一个余额查询网页
• 写一个链上数据机器人
• 做资产监控报警服务
• 构建 DeFi 数据面板
这一步,其实就是 Web3 后端开发的真正起点。
阅读原文:https://docs.polkadot.com/chain-interactions/query-data/query-sdks/#__tabbed_1_2
561

被折叠的 条评论
为什么被折叠?



