-
Notifications
You must be signed in to change notification settings - Fork 114
/
QueryService.ts
87 lines (69 loc) · 2.83 KB
/
QueryService.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { Hash, Header, BlockNumber, EventRecord, SignedBlock } from '@polkadot/types/interfaces';
import { Callback, Codec } from '@polkadot/types/types';
import { u32 } from '@polkadot/types/primitive';
import { ApiPromise } from '@polkadot/api';
import { getSpecTypes } from '@polkadot/types-known';
import { ISubstrateQueryService } from '.';
import { UnsubscribePromise } from '@polkadot/api/types';
export class QueryService implements ISubstrateQueryService {
// Enough large number
private readonly _versionReset = 99999999;
private _api: ApiPromise;
// Store runtime spec version
private _specVersion: u32;
constructor(api: ApiPromise) {
this._api = api;
this._specVersion = api.createType('u32', this._versionReset);
}
/**
* Update api metadata to the latest
*/
async resetMeta(): Promise<ApiPromise> {
return await this.ensureMeta(await this.getFinalizedHead());
}
/**
* Makes sure the api has correct types and metadata before fetching the block data
* @param blockHash Hash | Uint8Array | string
*/
async ensureMeta(blockHash: Hash | Uint8Array | string): Promise<ApiPromise> {
const api = this._api;
try {
const version = await api.rpc.state.getRuntimeVersion(blockHash);
const blockSpecVersion = version.specVersion;
// Register types for the block and update metadata if spec version is diffrent
if (!this._specVersion.eq(blockSpecVersion)) {
this._specVersion = blockSpecVersion;
const meta = await api.rpc.state.getMetadata(blockHash);
const chain = await api.rpc.system.chain();
api.registerTypes(getSpecTypes(api.registry, chain, version.specName, blockSpecVersion));
api.registry.setMetadata(meta);
}
} catch (error) {
console.error(`Failed to get Metadata for block ${JSON.stringify(blockHash, null, 2)}, using latest.`);
console.error(error);
this._specVersion = api.createType('u32', this._versionReset);
}
return api;
}
async getHeader(hash: Hash | Uint8Array | string): Promise<Header> {
const api = await this.ensureMeta(hash);
return api.rpc.chain.getHeader(hash);
}
getFinalizedHead(): Promise<Hash> {
return this._api.rpc.chain.getFinalizedHead();
}
subscribeNewHeads(v: Callback<Header>): UnsubscribePromise {
return this._api.rpc.chain.subscribeNewHeads(v);
}
getBlockHash(blockNumber?: BlockNumber | Uint8Array | number | string): Promise<Hash> {
return this._api.rpc.chain.getBlockHash(blockNumber);
}
async getBlock(hash: Hash | Uint8Array | string): Promise<SignedBlock> {
const api = await this.ensureMeta(hash);
return api.rpc.chain.getBlock(hash);
}
async eventsAt(hash: Hash | Uint8Array | string): Promise<EventRecord[] & Codec> {
const api = await this.ensureMeta(hash);
return api.query.system.events.at(hash);
}
}