0
# Blockchain Queries
1
2
Query blockchain state, constants, and runtime information through dynamically generated interfaces. The @polkadot/api provides structured access to all runtime storage items, constants, and derived data.
3
4
## Capabilities
5
6
### Storage Queries
7
8
Access chain state through the `query` interface, dynamically generated from runtime metadata.
9
10
```typescript { .api }
11
interface QueryableStorage<ApiType> {
12
[section: string]: {
13
[method: string]: QueryableStorageEntry<ApiType>;
14
};
15
}
16
17
interface QueryableStorageEntry<ApiType> {
18
/**
19
* Query storage with optional parameters
20
* @param ...args - Storage query parameters (if any)
21
* @returns Storage value or subscription
22
*/
23
(...args: any[]): ApiType extends 'rxjs'
24
? Observable<any>
25
: Promise<any>;
26
27
/**
28
* Query storage with subscription callback
29
* @param ...args - Storage query parameters and callback
30
* @returns Unsubscribe function
31
*/
32
(...args: any[], callback: (value: any) => void): ApiType extends 'rxjs'
33
? Observable<any>
34
: UnsubscribePromise;
35
36
/**
37
* Get the storage key for this query
38
* @param ...args - Storage query parameters
39
* @returns Storage key
40
*/
41
key(...args: any[]): StorageKey;
42
43
/**
44
* Get the raw storage key
45
* @param ...args - Storage query parameters
46
* @returns Raw key bytes
47
*/
48
keysPaged(options?: PaginationOptions): ApiType extends 'rxjs'
49
? Observable<StorageKey[]>
50
: Promise<StorageKey[]>;
51
}
52
53
interface PaginationOptions {
54
args?: any[];
55
pageSize?: number;
56
startKey?: string;
57
}
58
```
59
60
### Multi-Query Interface
61
62
Query multiple storage entries efficiently in a single subscription.
63
64
```typescript { .api }
65
interface QueryableStorageMulti<ApiType> {
66
/**
67
* Query multiple storage entries
68
* @param queries - Array of storage queries
69
* @param callback - Optional callback for subscriptions
70
* @returns Query results or unsubscribe function
71
*/
72
<T extends any[]>(
73
queries: (QueryableStorageEntry<'rxjs'> | [QueryableStorageEntry<'rxjs'>, ...any[]])[],
74
callback?: (values: T) => void
75
): ApiType extends 'rxjs'
76
? Observable<T>
77
: Promise<T>;
78
}
79
```
80
81
### Runtime Constants
82
83
Access module constants (parameter types) from the runtime.
84
85
```typescript { .api }
86
interface QueryableConsts<ApiType> {
87
[section: string]: {
88
[constant: string]: any;
89
};
90
}
91
```
92
93
### Derived Queries
94
95
Access computed data that combines multiple storage queries.
96
97
```typescript { .api }
98
interface AllDerives<ApiType> {
99
[section: string]: {
100
[method: string]: (...args: any[]) => ApiType extends 'rxjs'
101
? Observable<any>
102
: Promise<any>;
103
};
104
}
105
```
106
107
### Runtime Calls
108
109
Execute runtime API calls for specialized chain operations.
110
111
```typescript { .api }
112
interface QueryableCalls<ApiType> {
113
[api: string]: {
114
[method: string]: (...args: any[]) => ApiType extends 'rxjs'
115
? Observable<any>
116
: Promise<any>;
117
};
118
}
119
```
120
121
## Usage Examples
122
123
### Basic Storage Queries
124
125
```typescript
126
import { ApiPromise } from "@polkadot/api";
127
128
const api = await ApiPromise.create();
129
130
// Query account information
131
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
132
const accountInfo = await api.query.system.account(account);
133
console.log(`Free balance: ${accountInfo.data.free.toHuman()}`);
134
135
// Query current timestamp
136
const timestamp = await api.query.timestamp.now();
137
console.log(`Current timestamp: ${timestamp.toNumber()}`);
138
139
// Query all validator candidates
140
const validators = await api.query.staking.validators.entries();
141
validators.forEach(([key, prefs]) => {
142
const validator = key.args[0].toString();
143
console.log(`Validator: ${validator}, Commission: ${prefs.commission.toNumber() / 10000000}%`);
144
});
145
```
146
147
### Storage Subscriptions
148
149
```typescript
150
import { ApiPromise } from "@polkadot/api";
151
152
const api = await ApiPromise.create();
153
154
// Subscribe to account balance changes
155
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
156
const unsubscribe = await api.query.system.account(account, (accountInfo) => {
157
console.log(`New balance: ${accountInfo.data.free.toHuman()}`);
158
});
159
160
// Stop subscription
161
// unsubscribe();
162
163
// Subscribe to block number changes
164
const unsubBlockNumber = await api.query.system.number((blockNumber) => {
165
console.log(`Current block: ${blockNumber.toNumber()}`);
166
});
167
```
168
169
### Multi-Query Operations
170
171
```typescript
172
import { ApiPromise } from "@polkadot/api";
173
174
const api = await ApiPromise.create();
175
176
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
177
178
// Query multiple storage entries at once
179
const [accountInfo, blockNumber, timestamp] = await api.queryMulti([
180
[api.query.system.account, account],
181
api.query.system.number,
182
api.query.timestamp.now
183
]);
184
185
console.log(`Account: ${accountInfo.data.free.toHuman()}`);
186
console.log(`Block: ${blockNumber.toNumber()}`);
187
console.log(`Time: ${timestamp.toNumber()}`);
188
189
// Subscribe to multiple storage entries
190
const unsubscribe = await api.queryMulti([
191
[api.query.system.account, account],
192
api.query.system.number
193
], ([accountInfo, blockNumber]) => {
194
console.log(`Block ${blockNumber}: Balance ${accountInfo.data.free.toHuman()}`);
195
});
196
```
197
198
### Runtime Constants
199
200
```typescript
201
import { ApiPromise } from "@polkadot/api";
202
203
const api = await ApiPromise.create();
204
205
// Access module constants
206
const existentialDeposit = api.consts.balances.existentialDeposit;
207
console.log(`Existential deposit: ${existentialDeposit.toHuman()}`);
208
209
const blockTime = api.consts.babe.expectedBlockTime;
210
console.log(`Expected block time: ${blockTime.toNumber()}ms`);
211
212
const maxNominators = api.consts.staking.maxNominatorRewardedPerValidator;
213
console.log(`Max nominators per validator: ${maxNominators.toNumber()}`);
214
```
215
216
### Derived Queries
217
218
```typescript
219
import { ApiPromise } from "@polkadot/api";
220
221
const api = await ApiPromise.create();
222
223
// Get best block number
224
const bestNumber = await api.derive.chain.bestNumber();
225
console.log(`Best block: ${bestNumber.toNumber()}`);
226
227
// Get account balance info with locks
228
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
229
const balanceInfo = await api.derive.balances.all(account);
230
console.log(`Available balance: ${balanceInfo.availableBalance.toHuman()}`);
231
console.log(`Locked balance: ${balanceInfo.lockedBalance.toHuman()}`);
232
233
// Get validator exposure for current era
234
const currentEra = await api.query.staking.currentEra();
235
const validator = "1KvKReVmUiTc2LW2a4qyHy3PeGk1RbFw67rZE4TaFvZw6Z3";
236
const exposure = await api.derive.staking.account(validator);
237
console.log(`Total stake: ${exposure.stakingLedger?.total.toHuman()}`);
238
```
239
240
### Runtime API Calls
241
242
```typescript
243
import { ApiPromise } from "@polkadot/api";
244
245
const api = await ApiPromise.create();
246
247
// Get account next nonce
248
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
249
const nonce = await api.rpc.system.accountNextIndex(account);
250
console.log(`Next nonce: ${nonce.toNumber()}`);
251
252
// Validate a transaction
253
const tx = api.tx.balances.transferAllowDeath(account, 1000000000000);
254
const info = await api.call.transactionPaymentApi.queryInfo(tx.toHex(), tx.encodedLength);
255
console.log(`Transaction fee: ${info.partialFee.toHuman()}`);
256
```
257
258
### Storage Keys and Pagination
259
260
```typescript
261
import { ApiPromise } from "@polkadot/api";
262
263
const api = await ApiPromise.create();
264
265
// Get storage key for specific query
266
const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";
267
const key = api.query.system.account.key(account);
268
console.log(`Storage key: ${key.toHex()}`);
269
270
// Paginated storage queries
271
const validatorKeys = await api.query.staking.validators.keysPaged({
272
pageSize: 100
273
});
274
console.log(`Found ${validatorKeys.length} validators`);
275
276
// Get all entries with pagination
277
let allValidators = [];
278
let lastKey = null;
279
280
do {
281
const pageKeys = await api.query.staking.validators.keysPaged({
282
pageSize: 100,
283
startKey: lastKey
284
});
285
286
if (pageKeys.length === 0) break;
287
288
const pageEntries = await api.query.staking.validators.multi(pageKeys);
289
allValidators = allValidators.concat(pageEntries);
290
lastKey = pageKeys[pageKeys.length - 1].toHex();
291
} while (true);
292
293
console.log(`Total validators: ${allValidators.length}`);
294
```
295
296
### RxJS Storage Queries
297
298
```typescript
299
import { ApiRx } from "@polkadot/api";
300
import { switchMap, map, combineLatest } from "rxjs";
301
302
const api$ = ApiRx.create();
303
304
// Subscribe to account balance changes with RxJS
305
api$.pipe(
306
switchMap(api => api.query.system.account("1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg"))
307
).subscribe(accountInfo => {
308
console.log(`Balance: ${accountInfo.data.free.toHuman()}`);
309
});
310
311
// Combine multiple storage subscriptions
312
api$.pipe(
313
switchMap(api =>
314
combineLatest([
315
api.query.system.number(),
316
api.query.timestamp.now()
317
])
318
)
319
).subscribe(([blockNumber, timestamp]) => {
320
console.log(`Block ${blockNumber} at ${new Date(timestamp.toNumber())}`);
321
});
322
```