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

rpc-operations.mddocs/

0

# RPC Operations

1

2

Direct access to node RPC methods for chain information, state queries, and system operations. The RPC interface provides raw access to the underlying blockchain node functionality through standardized JSON-RPC calls.

3

4

## Capabilities

5

6

### Chain RPC Methods

7

8

Access blockchain and block-related information.

9

10

```typescript { .api }

11

interface ChainRpc<ApiType> {

12

/**

13

* Get block by hash

14

* @param hash - Block hash (optional, defaults to best block)

15

* @returns Block information

16

*/

17

getBlock(hash?: Hash): ApiType extends 'rxjs' ? Observable<SignedBlock> : Promise<SignedBlock>;

18

19

/**

20

* Get block hash by number

21

* @param blockNumber - Block number (optional, defaults to best block)

22

* @returns Block hash

23

*/

24

getBlockHash(blockNumber?: BlockNumber): ApiType extends 'rxjs' ? Observable<Hash> : Promise<Hash>;

25

26

/**

27

* Get block header by hash

28

* @param hash - Block hash (optional, defaults to best block)

29

* @returns Block header

30

*/

31

getHeader(hash?: Hash): ApiType extends 'rxjs' ? Observable<Header> : Promise<Header>;

32

33

/**

34

* Subscribe to new block headers

35

* @param callback - Callback function for new headers

36

* @returns Unsubscribe function or Observable

37

*/

38

subscribeNewHeads(callback?: (header: Header) => void): ApiType extends 'rxjs'

39

? Observable<Header>

40

: UnsubscribePromise;

41

42

/**

43

* Subscribe to all new block headers including forks

44

* @param callback - Callback function for new headers

45

* @returns Unsubscribe function or Observable

46

*/

47

subscribeAllHeads(callback?: (header: Header) => void): ApiType extends 'rxjs'

48

? Observable<Header>

49

: UnsubscribePromise;

50

51

/**

52

* Subscribe to finalized block headers

53

* @param callback - Callback function for finalized headers

54

* @returns Unsubscribe function or Observable

55

*/

56

subscribeFinalizedHeads(callback?: (header: Header) => void): ApiType extends 'rxjs'

57

? Observable<Header>

58

: UnsubscribePromise;

59

}

60

```

61

62

### State RPC Methods

63

64

Query and subscribe to chain state changes.

65

66

```typescript { .api }

67

interface StateRpc<ApiType> {

68

/**

69

* Get storage value by key

70

* @param key - Storage key

71

* @param at - Block hash to query at (optional)

72

* @returns Storage value

73

*/

74

getStorage(key: StorageKey, at?: Hash): ApiType extends 'rxjs'

75

? Observable<StorageData | null>

76

: Promise<StorageData | null>;

77

78

/**

79

* Get multiple storage values by keys

80

* @param keys - Array of storage keys

81

* @param at - Block hash to query at (optional)

82

* @returns Array of storage values

83

*/

84

queryStorage(keys: StorageKey[], at?: Hash): ApiType extends 'rxjs'

85

? Observable<[Hash, StorageChangeSet][]>

86

: Promise<[Hash, StorageChangeSet][]>;

87

88

/**

89

* Subscribe to storage changes

90

* @param keys - Storage keys to watch

91

* @param callback - Callback for storage changes

92

* @returns Unsubscribe function or Observable

93

*/

94

subscribeStorage(

95

keys: StorageKey[],

96

callback?: (changes: StorageChangeSet) => void

97

): ApiType extends 'rxjs'

98

? Observable<StorageChangeSet>

99

: UnsubscribePromise;

100

101

/**

102

* Get runtime metadata

103

* @param at - Block hash to query at (optional)

104

* @returns Runtime metadata

105

*/

106

getMetadata(at?: Hash): ApiType extends 'rxjs'

107

? Observable<Metadata>

108

: Promise<Metadata>;

109

110

/**

111

* Get runtime version

112

* @param at - Block hash to query at (optional)

113

* @returns Runtime version

114

*/

115

getRuntimeVersion(at?: Hash): ApiType extends 'rxjs'

116

? Observable<RuntimeVersion>

117

: Promise<RuntimeVersion>;

118

119

/**

120

* Call runtime API method

121

* @param method - Runtime API method name

122

* @param data - Method parameters

123

* @param at - Block hash to query at (optional)

124

* @returns Runtime API result

125

*/

126

call(method: string, data: Bytes, at?: Hash): ApiType extends 'rxjs'

127

? Observable<Bytes>

128

: Promise<Bytes>;

129

130

/**

131

* Get storage keys with pagination

132

* @param prefix - Storage key prefix

133

* @param pageSize - Number of keys per page

134

* @param startKey - Starting key for pagination

135

* @param at - Block hash to query at (optional)

136

* @returns Array of storage keys

137

*/

138

getKeysPaged(

139

prefix: StorageKey,

140

pageSize: number,

141

startKey?: StorageKey,

142

at?: Hash

143

): ApiType extends 'rxjs'

144

? Observable<StorageKey[]>

145

: Promise<StorageKey[]>;

146

}

147

```

148

149

### System RPC Methods

150

151

Access node and network information.

152

153

```typescript { .api }

154

interface SystemRpc<ApiType> {

155

/**

156

* Get chain name

157

* @returns Chain name

158

*/

159

chain(): ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;

160

161

/**

162

* Get node name

163

* @returns Node implementation name

164

*/

165

name(): ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;

166

167

/**

168

* Get node version

169

* @returns Node version

170

*/

171

version(): ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;

172

173

/**

174

* Get account next index (nonce)

175

* @param account - Account address

176

* @returns Account nonce

177

*/

178

accountNextIndex(account: AccountId): ApiType extends 'rxjs'

179

? Observable<Index>

180

: Promise<Index>;

181

182

/**

183

* Add reserved peer

184

* @param peer - Peer multiaddress

185

* @returns Success result

186

*/

187

addReservedPeer(peer: string): ApiType extends 'rxjs'

188

? Observable<Text>

189

: Promise<Text>;

190

191

/**

192

* Get node health status

193

* @returns Health information

194

*/

195

health(): ApiType extends 'rxjs' ? Observable<Health> : Promise<Health>;

196

197

/**

198

* Get local peer ID

199

* @returns Peer ID

200

*/

201

localPeerId(): ApiType extends 'rxjs' ? Observable<Text> : Promise<Text>;

202

203

/**

204

* Get connected peers

205

* @returns Array of peer information

206

*/

207

peers(): ApiType extends 'rxjs' ? Observable<PeerInfo[]> : Promise<PeerInfo[]>;

208

209

/**

210

* Get node properties

211

* @returns Node properties

212

*/

213

properties(): ApiType extends 'rxjs' ? Observable<ChainProperties> : Promise<ChainProperties>;

214

}

215

```

216

217

### Author RPC Methods

218

219

Submit and manage transactions in the transaction pool.

220

221

```typescript { .api }

222

interface AuthorRpc<ApiType> {

223

/**

224

* Submit transaction to the pool

225

* @param extrinsic - Signed extrinsic

226

* @returns Transaction hash

227

*/

228

submitExtrinsic(extrinsic: Extrinsic): ApiType extends 'rxjs'

229

? Observable<Hash>

230

: Promise<Hash>;

231

232

/**

233

* Submit and watch transaction status

234

* @param extrinsic - Signed extrinsic

235

* @param callback - Status callback

236

* @returns Unsubscribe function or Observable

237

*/

238

submitAndWatchExtrinsic(

239

extrinsic: Extrinsic,

240

callback?: (status: ExtrinsicStatus) => void

241

): ApiType extends 'rxjs'

242

? Observable<ExtrinsicStatus>

243

: UnsubscribePromise;

244

245

/**

246

* Get pending extrinsics

247

* @returns Array of pending extrinsics

248

*/

249

pendingExtrinsics(): ApiType extends 'rxjs'

250

? Observable<Extrinsic[]>

251

: Promise<Extrinsic[]>;

252

253

/**

254

* Remove extrinsic from pool

255

* @param bytesOrHash - Extrinsic bytes or hash

256

* @returns Array of removed transaction hashes

257

*/

258

removeExtrinsic(bytesOrHash: Vec<ExtrinsicOrHash>): ApiType extends 'rxjs'

259

? Observable<Hash[]>

260

: Promise<Hash[]>;

261

}

262

```

263

264

## Usage Examples

265

266

### Chain Information Queries

267

268

```typescript

269

import { ApiPromise } from "@polkadot/api";

270

271

const api = await ApiPromise.create();

272

273

// Get basic chain information

274

const [chain, nodeName, nodeVersion] = await Promise.all([

275

api.rpc.system.chain(),

276

api.rpc.system.name(),

277

api.rpc.system.version()

278

]);

279

280

console.log(`Connected to ${chain} using ${nodeName} v${nodeVersion}`);

281

282

// Get current block information

283

const bestHash = await api.rpc.chain.getBlockHash();

284

const bestBlock = await api.rpc.chain.getBlock(bestHash);

285

const header = bestBlock.block.header;

286

287

console.log(`Best block: #${header.number} (${bestHash})`);

288

console.log(`Parent hash: ${header.parentHash}`);

289

console.log(`State root: ${header.stateRoot}`);

290

```

291

292

### Block Subscriptions

293

294

```typescript

295

import { ApiPromise } from "@polkadot/api";

296

297

const api = await ApiPromise.create();

298

299

// Subscribe to new blocks

300

const unsubscribeHeads = await api.rpc.chain.subscribeNewHeads((header) => {

301

console.log(`New block #${header.number} with hash ${header.hash}`);

302

console.log(` Parent: ${header.parentHash}`);

303

console.log(` Extrinsics root: ${header.extrinsicsRoot}`);

304

});

305

306

// Subscribe to finalized blocks only

307

const unsubscribeFinalized = await api.rpc.chain.subscribeFinalizedHeads((header) => {

308

console.log(`Finalized block #${header.number}`);

309

});

310

311

// Stop subscriptions

312

// unsubscribeHeads();

313

// unsubscribeFinalized();

314

```

315

316

### State Queries

317

318

```typescript

319

import { ApiPromise } from "@polkadot/api";

320

321

const api = await ApiPromise.create();

322

323

// Query specific storage item

324

const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";

325

const storageKey = api.query.system.account.key(account);

326

const accountData = await api.rpc.state.getStorage(storageKey);

327

328

if (accountData) {

329

const decoded = api.createType('AccountInfo', accountData);

330

console.log(`Balance: ${decoded.data.free.toHuman()}`);

331

}

332

333

// Query at specific block

334

const blockHash = await api.rpc.chain.getBlockHash(1000000);

335

const historicalData = await api.rpc.state.getStorage(storageKey, blockHash);

336

```

337

338

### Storage Subscriptions

339

340

```typescript

341

import { ApiPromise } from "@polkadot/api";

342

343

const api = await ApiPromise.create();

344

345

// Subscribe to storage changes

346

const account = "1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg";

347

const storageKey = api.query.system.account.key(account);

348

349

const unsubscribe = await api.rpc.state.subscribeStorage([storageKey], (changes) => {

350

console.log(`Block: ${changes.block}`);

351

changes.changes.forEach(([key, value]) => {

352

if (value) {

353

const decoded = api.createType('AccountInfo', value);

354

console.log(`Account balance changed: ${decoded.data.free.toHuman()}`);

355

}

356

});

357

});

358

```

359

360

### Transaction Submission

361

362

```typescript

363

import { ApiPromise } from "@polkadot/api";

364

import { Keyring } from "@polkadot/keyring";

365

366

const api = await ApiPromise.create();

367

const keyring = new Keyring({ type: 'sr25519' });

368

369

// Create account from seed

370

const alice = keyring.addFromUri('//Alice');

371

372

// Create and sign transaction

373

const transfer = api.tx.balances.transferAllowDeath(

374

'1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg',

375

1000000000000

376

);

377

378

const signedTx = await transfer.signAsync(alice);

379

380

// Submit transaction

381

const txHash = await api.rpc.author.submitExtrinsic(signedTx);

382

console.log(`Transaction submitted: ${txHash}`);

383

384

// Submit and watch transaction

385

const unsubscribe = await api.rpc.author.submitAndWatchExtrinsic(signedTx, (status) => {

386

console.log(`Transaction status: ${status.type}`);

387

388

if (status.isInBlock) {

389

console.log(`Included in block: ${status.asInBlock}`);

390

} else if (status.isFinalized) {

391

console.log(`Finalized in block: ${status.asFinalized}`);

392

unsubscribe();

393

} else if (status.isError) {

394

console.log('Transaction error');

395

unsubscribe();

396

}

397

});

398

```

399

400

### Runtime API Calls

401

402

```typescript

403

import { ApiPromise } from "@polkadot/api";

404

405

const api = await ApiPromise.create();

406

407

// Get runtime metadata

408

const metadata = await api.rpc.state.getMetadata();

409

console.log(`Metadata version: ${metadata.version}`);

410

411

// Get runtime version

412

const runtimeVersion = await api.rpc.state.getRuntimeVersion();

413

console.log(`Runtime: ${runtimeVersion.specName} v${runtimeVersion.specVersion}`);

414

415

// Call custom runtime API

416

const method = 'TransactionPaymentApi_query_info';

417

const tx = api.tx.balances.transferAllowDeath('1FRMM8PEiWXYax7rpS6X4XZX1aAAxSWx1CrKTyrVYhV24fg', 1000);

418

const callData = api.createType('(Bytes, u32)', [tx.toHex(), tx.encodedLength]).toHex();

419

420

const result = await api.rpc.state.call(method, callData);

421

const feeInfo = api.createType('RuntimeDispatchInfo', result);

422

console.log(`Transaction fee: ${feeInfo.partialFee.toHuman()}`);

423

```

424

425

### Node Information

426

427

```typescript

428

import { ApiPromise } from "@polkadot/api";

429

430

const api = await ApiPromise.create();

431

432

// Get node health

433

const health = await api.rpc.system.health();

434

console.log(`Peers: ${health.peers}, Syncing: ${health.isSyncing}`);

435

436

// Get connected peers

437

const peers = await api.rpc.system.peers();

438

console.log(`Connected to ${peers.length} peers:`);

439

peers.forEach(peer => {

440

console.log(` ${peer.peerId}: ${peer.roles.toString()}`);

441

});

442

443

// Get chain properties

444

const properties = await api.rpc.system.properties();

445

console.log(`SS58 Format: ${properties.ss58Format?.toNumber()}`);

446

console.log(`Token symbol: ${properties.tokenSymbol?.toString()}`);

447

console.log(`Token decimals: ${properties.tokenDecimals?.toNumber()}`);

448

```

449

450

### RxJS RPC Operations

451

452

```typescript

453

import { ApiRx } from "@polkadot/api";

454

import { switchMap, tap } from "rxjs";

455

456

const api$ = ApiRx.create();

457

458

// Chain RxJS operations

459

api$.pipe(

460

switchMap(api => api.rpc.chain.subscribeNewHeads()),

461

tap(header => console.log(`Block #${header.number}`)),

462

switchMap(header => api$.pipe(

463

switchMap(api => api.rpc.chain.getBlock(header.hash))

464

))

465

).subscribe(block => {

466

console.log(`Block has ${block.block.extrinsics.length} extrinsics`);

467

});

468

469

// Combine multiple RPC streams

470

import { combineLatest } from "rxjs";

471

472

api$.pipe(

473

switchMap(api =>

474

combineLatest([

475

api.rpc.chain.subscribeNewHeads(),

476

api.rpc.system.health()

477

])

478

)

479

).subscribe(([header, health]) => {

480

console.log(`Block #${header.number}, Peers: ${health.peers}`);

481

});

482

```