or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

api-initialization.mdblockchain-queries.mdevents-metadata.mdindex.mdnetwork-providers.mdrpc-operations.mdtransaction-submission.md

blockchain-queries.mddocs/

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

```