@dedot/api 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -197,9 +197,12 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
197
197
  await this._localCache?.clear();
198
198
  }
199
199
  async doConnect() {
200
+ // @ts-ignore
200
201
  this.on('connected', this.onConnected);
202
+ // @ts-ignore
201
203
  this.on('disconnected', this.onDisconnected);
202
204
  return new Promise((resolve) => {
205
+ // @ts-ignore
203
206
  this.once('ready', () => {
204
207
  resolve(this);
205
208
  });
@@ -212,6 +215,7 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
212
215
  async initialize() {
213
216
  await this.initializeLocalCache();
214
217
  await this.doInitialize();
218
+ // @ts-ignore
215
219
  this.emit('ready');
216
220
  }
217
221
  async doInitialize() {
@@ -85,6 +85,11 @@ class DedotClient// prettier-end-here
85
85
  }
86
86
  await this.setupMetadata(metadata);
87
87
  this.subscribeRuntimeUpgrades();
88
+ // relegate events
89
+ this.chainHead.on('newBlock', (...args) => this.emit('newBlock', ...args));
90
+ this.chainHead.on('bestBlock', (...args) => this.emit('bestBlock', ...args));
91
+ this.chainHead.on('finalizedBlock', (...args) => this.emit('finalizedBlock', ...args));
92
+ this.chainHead.on('bestChainChanged', (...args) => this.emit('bestChainChanged', ...args));
88
93
  }
89
94
  /**
90
95
  * Ref: https://github.com/paritytech/polkadot-sdk/blob/bbd51ce867967f71657b901f1a956ad4f75d352e/substrate/frame/system/src/lib.rs#L909-L913
@@ -138,8 +138,13 @@ class LegacyClient// prettier-end-here
138
138
  if (!this.#runtimeSubscriptionUnsub) {
139
139
  return;
140
140
  }
141
- await this.#runtimeSubscriptionUnsub();
142
- this.#runtimeSubscriptionUnsub = undefined;
141
+ try {
142
+ await this.#runtimeSubscriptionUnsub();
143
+ this.#runtimeSubscriptionUnsub = undefined;
144
+ }
145
+ catch {
146
+ // ignore
147
+ }
143
148
  }
144
149
  #subscribeUpdates() {
145
150
  this.#subscribeRuntimeUpgrades();
@@ -163,8 +163,8 @@ class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic_js_1.BaseSubmittab
163
163
  status: { type: 'Broadcasting' },
164
164
  txHash,
165
165
  }));
166
- const stopBestBlockTrackingFn = api.chainHead.on('bestBlock', checkBestBlockIncluded);
167
- const stopFinalizedBlockTrackingFn = api.chainHead.on('finalizedBlock', checkFinalizedBlockIncluded);
166
+ const stopBestBlockTrackingFn = api.on('bestBlock', checkBestBlockIncluded);
167
+ const stopFinalizedBlockTrackingFn = api.on('finalizedBlock', checkFinalizedBlockIncluded);
168
168
  const stopTracking = () => {
169
169
  stopBestBlockTrackingFn();
170
170
  stopFinalizedBlockTrackingFn();
@@ -360,7 +360,17 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
360
360
  if (!runtimeEvent)
361
361
  return;
362
362
  if (runtimeEvent.type == 'valid') {
363
- return runtimeEvent.spec;
363
+ const newRuntimeVersion = runtimeEvent.spec;
364
+ // fix inconsistent type of returned apis
365
+ // in some network endpoints this newRuntimeVersion.apis is an array (maybe using an old version of the sdk)
366
+ // here we convert it to a map format for consistency.
367
+ if (Array.isArray(newRuntimeVersion.apis)) {
368
+ newRuntimeVersion.apis = newRuntimeVersion.apis.reduce((o, [name, version]) => {
369
+ o[name] = version;
370
+ return o;
371
+ }, {});
372
+ }
373
+ return newRuntimeVersion;
364
374
  }
365
375
  // If the runtime is invalid,
366
376
  // we safely return an undefined runtime for now
@@ -24,7 +24,7 @@ class NewStorageQuery extends BaseStorageQuery_js_1.BaseStorageQuery {
24
24
  */
25
25
  async query(keys, at) {
26
26
  // Query storage using ChainHead API
27
- const storageQueries = keys.map(key => ({ type: 'value', key }));
27
+ const storageQueries = keys.map((key) => ({ type: 'value', key }));
28
28
  // Use the provided block hash or skip it in tests
29
29
  const rawResults = at
30
30
  ? await this.client.chainHead.storage(storageQueries, undefined, at)
@@ -32,7 +32,7 @@ class NewStorageQuery extends BaseStorageQuery_js_1.BaseStorageQuery {
32
32
  // Create a map of key -> value for easy lookup
33
33
  const results = {};
34
34
  // Initialize all keys with undefined
35
- keys.forEach(key => results[key] = undefined);
35
+ keys.forEach((key) => (results[key] = undefined));
36
36
  // Update with actual values from the response
37
37
  rawResults.forEach((result) => {
38
38
  results[result.key] = result.value ?? undefined;
@@ -54,7 +54,7 @@ class NewStorageQuery extends BaseStorageQuery_js_1.BaseStorageQuery {
54
54
  // Function to pull storage values and call the callback if there are changes
55
55
  const pull = async ({ hash }) => {
56
56
  // Query storage using ChainHead API
57
- const storageQueries = keys.map(key => ({ type: 'value', key }));
57
+ const storageQueries = keys.map((key) => ({ type: 'value', key }));
58
58
  const rawResults = await this.client.chainHead.storage(storageQueries, undefined, hash);
59
59
  let changed = false;
60
60
  // Create a map for easy lookup
@@ -76,7 +76,7 @@ class NewStorageQuery extends BaseStorageQuery_js_1.BaseStorageQuery {
76
76
  // Initial pull
77
77
  await pull(best);
78
78
  // Subscribe to best block events
79
- const unsub = this.client.chainHead.on('bestBlock', pull);
79
+ const unsub = this.client.on('bestBlock', pull);
80
80
  return async () => {
81
81
  unsub();
82
82
  };
@@ -12,7 +12,7 @@ export declare function ensurePresence<T>(value: T): NonNullable<T>;
12
12
  * @name BaseSubstrateClient
13
13
  * @description Base & shared abstraction for Substrate API Clients
14
14
  */
15
- export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends JsonRpcClient<ChainApi, ApiEvent> implements ISubstrateClient<ChainApi[Rv]> {
15
+ export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi, Events extends string = ApiEvent> extends JsonRpcClient<ChainApi, Events> implements ISubstrateClient<ChainApi[Rv], Events> {
16
16
  rpcVersion: RpcVersion;
17
17
  protected _options: ApiOptions;
18
18
  protected _registry?: PortableRegistry;
@@ -193,9 +193,12 @@ export class BaseSubstrateClient extends JsonRpcClient {
193
193
  await this._localCache?.clear();
194
194
  }
195
195
  async doConnect() {
196
+ // @ts-ignore
196
197
  this.on('connected', this.onConnected);
198
+ // @ts-ignore
197
199
  this.on('disconnected', this.onDisconnected);
198
200
  return new Promise((resolve) => {
201
+ // @ts-ignore
199
202
  this.once('ready', () => {
200
203
  resolve(this);
201
204
  });
@@ -208,6 +211,7 @@ export class BaseSubstrateClient extends JsonRpcClient {
208
211
  async initialize() {
209
212
  await this.initializeLocalCache();
210
213
  await this.doInitialize();
214
+ // @ts-ignore
211
215
  this.emit('ready');
212
216
  }
213
217
  async doInitialize() {
@@ -4,7 +4,7 @@ import { GenericSubstrateApi, RpcV2, RpcVersion, VersionedGenericSubstrateApi }
4
4
  import type { SubstrateApi } from '../chaintypes/index.js';
5
5
  import { ChainHead, ChainSpec, PinnedBlock } from '../json-rpc/index.js';
6
6
  import { BaseStorageQuery } from '../storage/index.js';
7
- import type { ApiOptions, ISubstrateClientAt, TxBroadcaster } from '../types.js';
7
+ import type { ApiOptions, DedotClientEvent, ISubstrateClientAt, TxBroadcaster } from '../types.js';
8
8
  import { BaseSubstrateClient } from './BaseSubstrateClient.js';
9
9
  /**
10
10
  * @name DedotClient
@@ -13,7 +13,7 @@ import { BaseSubstrateClient } from './BaseSubstrateClient.js';
13
13
  * __Unstable, use with caution.__
14
14
  */
15
15
  export declare class DedotClient<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>// prettier-end-here
16
- extends BaseSubstrateClient<RpcV2, ChainApi> {
16
+ extends BaseSubstrateClient<RpcV2, ChainApi, DedotClientEvent> {
17
17
  #private;
18
18
  protected _chainHead?: ChainHead;
19
19
  protected _chainSpec?: ChainSpec;
@@ -82,6 +82,11 @@ export class DedotClient// prettier-end-here
82
82
  }
83
83
  await this.setupMetadata(metadata);
84
84
  this.subscribeRuntimeUpgrades();
85
+ // relegate events
86
+ this.chainHead.on('newBlock', (...args) => this.emit('newBlock', ...args));
87
+ this.chainHead.on('bestBlock', (...args) => this.emit('bestBlock', ...args));
88
+ this.chainHead.on('finalizedBlock', (...args) => this.emit('finalizedBlock', ...args));
89
+ this.chainHead.on('bestChainChanged', (...args) => this.emit('bestChainChanged', ...args));
85
90
  }
86
91
  /**
87
92
  * Ref: https://github.com/paritytech/polkadot-sdk/blob/bbd51ce867967f71657b901f1a956ad4f75d352e/substrate/frame/system/src/lib.rs#L909-L913
@@ -135,8 +135,13 @@ export class LegacyClient// prettier-end-here
135
135
  if (!this.#runtimeSubscriptionUnsub) {
136
136
  return;
137
137
  }
138
- await this.#runtimeSubscriptionUnsub();
139
- this.#runtimeSubscriptionUnsub = undefined;
138
+ try {
139
+ await this.#runtimeSubscriptionUnsub();
140
+ this.#runtimeSubscriptionUnsub = undefined;
141
+ }
142
+ catch {
143
+ // ignore
144
+ }
140
145
  }
141
146
  #subscribeUpdates() {
142
147
  this.#subscribeRuntimeUpgrades();
@@ -160,8 +160,8 @@ export class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
160
160
  status: { type: 'Broadcasting' },
161
161
  txHash,
162
162
  }));
163
- const stopBestBlockTrackingFn = api.chainHead.on('bestBlock', checkBestBlockIncluded);
164
- const stopFinalizedBlockTrackingFn = api.chainHead.on('finalizedBlock', checkFinalizedBlockIncluded);
163
+ const stopBestBlockTrackingFn = api.on('bestBlock', checkBestBlockIncluded);
164
+ const stopFinalizedBlockTrackingFn = api.on('finalizedBlock', checkFinalizedBlockIncluded);
165
165
  const stopTracking = () => {
166
166
  stopBestBlockTrackingFn();
167
167
  stopFinalizedBlockTrackingFn();
@@ -357,7 +357,17 @@ export class ChainHead extends JsonRpcGroup {
357
357
  if (!runtimeEvent)
358
358
  return;
359
359
  if (runtimeEvent.type == 'valid') {
360
- return runtimeEvent.spec;
360
+ const newRuntimeVersion = runtimeEvent.spec;
361
+ // fix inconsistent type of returned apis
362
+ // in some network endpoints this newRuntimeVersion.apis is an array (maybe using an old version of the sdk)
363
+ // here we convert it to a map format for consistency.
364
+ if (Array.isArray(newRuntimeVersion.apis)) {
365
+ newRuntimeVersion.apis = newRuntimeVersion.apis.reduce((o, [name, version]) => {
366
+ o[name] = version;
367
+ return o;
368
+ }, {});
369
+ }
370
+ return newRuntimeVersion;
361
371
  }
362
372
  // If the runtime is invalid,
363
373
  // we safely return an undefined runtime for now
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@dedot/api",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
5
- "author": "Thang X. Vu <thang@coongcrafts.io>",
6
- "homepage": "https://github.com/dedotdev/dedot/tree/main/packages/api",
5
+ "author": "Thang X. Vu <thang@dedot.dev>",
6
+ "homepage": "https://dedot.dev",
7
7
  "repository": {
8
8
  "directory": "packages/api",
9
9
  "type": "git",
@@ -13,13 +13,13 @@
13
13
  "type": "module",
14
14
  "sideEffects": false,
15
15
  "dependencies": {
16
- "@dedot/codecs": "0.9.0",
17
- "@dedot/providers": "0.9.0",
18
- "@dedot/runtime-specs": "0.9.0",
19
- "@dedot/shape": "0.9.0",
20
- "@dedot/storage": "0.9.0",
21
- "@dedot/types": "0.9.0",
22
- "@dedot/utils": "0.9.0"
16
+ "@dedot/codecs": "0.9.2",
17
+ "@dedot/providers": "0.9.2",
18
+ "@dedot/runtime-specs": "0.9.2",
19
+ "@dedot/shape": "0.9.2",
20
+ "@dedot/storage": "0.9.2",
21
+ "@dedot/types": "0.9.2",
22
+ "@dedot/utils": "0.9.2"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json",
@@ -48,7 +48,7 @@
48
48
  "node": ">=18"
49
49
  },
50
50
  "license": "Apache-2.0",
51
- "gitHead": "cebae55a3525e2c9bcdd70322027855a594a287d",
51
+ "gitHead": "b28ae48371785d44bf734cf45a5b8d0716d9bd70",
52
52
  "module": "./index.js",
53
53
  "types": "./index.d.ts"
54
54
  }
@@ -21,7 +21,7 @@ export class NewStorageQuery extends BaseStorageQuery {
21
21
  */
22
22
  async query(keys, at) {
23
23
  // Query storage using ChainHead API
24
- const storageQueries = keys.map(key => ({ type: 'value', key }));
24
+ const storageQueries = keys.map((key) => ({ type: 'value', key }));
25
25
  // Use the provided block hash or skip it in tests
26
26
  const rawResults = at
27
27
  ? await this.client.chainHead.storage(storageQueries, undefined, at)
@@ -29,7 +29,7 @@ export class NewStorageQuery extends BaseStorageQuery {
29
29
  // Create a map of key -> value for easy lookup
30
30
  const results = {};
31
31
  // Initialize all keys with undefined
32
- keys.forEach(key => results[key] = undefined);
32
+ keys.forEach((key) => (results[key] = undefined));
33
33
  // Update with actual values from the response
34
34
  rawResults.forEach((result) => {
35
35
  results[result.key] = result.value ?? undefined;
@@ -51,7 +51,7 @@ export class NewStorageQuery extends BaseStorageQuery {
51
51
  // Function to pull storage values and call the callback if there are changes
52
52
  const pull = async ({ hash }) => {
53
53
  // Query storage using ChainHead API
54
- const storageQueries = keys.map(key => ({ type: 'value', key }));
54
+ const storageQueries = keys.map((key) => ({ type: 'value', key }));
55
55
  const rawResults = await this.client.chainHead.storage(storageQueries, undefined, hash);
56
56
  let changed = false;
57
57
  // Create a map for easy lookup
@@ -73,7 +73,7 @@ export class NewStorageQuery extends BaseStorageQuery {
73
73
  // Initial pull
74
74
  await pull(best);
75
75
  // Subscribe to best block events
76
- const unsub = this.client.chainHead.on('bestBlock', pull);
76
+ const unsub = this.client.on('bestBlock', pull);
77
77
  return async () => {
78
78
  unsub();
79
79
  };
package/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ChainHeadEvent } from '@dedot/api/json-rpc';
1
2
  import { BlockHash, Hash, Metadata, PortableRegistry } from '@dedot/codecs';
2
3
  import type { ConnectionStatus, JsonRpcProvider, ProviderEvent } from '@dedot/providers';
3
4
  import type { AnyShape } from '@dedot/shape';
@@ -61,6 +62,7 @@ export interface ApiOptions extends JsonRpcClientOptions {
61
62
  signer?: InjectedSigner;
62
63
  }
63
64
  export type ApiEvent = ProviderEvent | 'ready' | 'runtimeUpgraded';
65
+ export type DedotClientEvent = ApiEvent | ChainHeadEvent;
64
66
  export interface SubstrateRuntimeVersion {
65
67
  specName: string;
66
68
  implName: string;