@novasamatech/host-substrate-chain-connection 0.7.5 → 0.7.6

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.
Files changed (2) hide show
  1. package/README.md +95 -11
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -24,12 +24,16 @@ import {
24
24
  } from '@novasamatech/host-substrate-chain-connection';
25
25
  import { dot } from '@polkadot-api/descriptors';
26
26
 
27
- const polkadot: ChainConfig = {
27
+ // `ChainConfig` only requires `genesisHash` — extend it with whatever fields
28
+ // your app needs (here, the WebSocket endpoints to dial).
29
+ type Chain = ChainConfig & { nodes: string[] };
30
+
31
+ const polkadot: Chain = {
28
32
  genesisHash: '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3',
29
33
  nodes: ['wss://rpc.polkadot.io'],
30
34
  };
31
35
 
32
- const chains = createChainConnection({
36
+ const chains = createChainConnection<Chain>({
33
37
  createProvider: (chain, onStatusChanged) =>
34
38
  createWsJsonRpcProvider({
35
39
  endpoints: chain.nodes,
@@ -51,8 +55,10 @@ unlock();
51
55
  - [`lockApi`](#lockapichain)
52
56
  - [`getProvider`](#getproviderchain)
53
57
  - [`status` / `onStatusChanged`](#statusgenesishash--onstatuschangedgenesishash-callback)
58
+ - [`pauseAll` / `resumeAll`](#pauseall--resumeall)
54
59
  - [`createWsJsonRpcProvider`](#createwsjsonrpcprovideroptions)
55
60
  - [`createMetadataCache`](#createmetadatacacheoptions)
61
+ - [`withSubscriptionReplay`](#withsubscriptionreplayprovider-onreconnect)
56
62
  - [Recipes](#recipes)
57
63
  - [Custom resolve](#custom-resolve)
58
64
  - [Metadata caching](#metadata-caching)
@@ -88,10 +94,11 @@ function createChainConnection<C extends ChainConfig, T = PolkadotClient>(
88
94
  ```ts
89
95
  type ChainConfig = {
90
96
  genesisHash: string;
91
- nodes: string[];
92
97
  };
93
98
  ```
94
99
 
100
+ Extend it with whatever fields your `createProvider` / `resolve` callbacks need (e.g. `nodes`, `name`, `specName`).
101
+
95
102
  Returns a [`ChainConnection<C, T>`](#lockapichain) with the methods below.
96
103
 
97
104
  ---
@@ -176,19 +183,66 @@ unsubscribe();
176
183
 
177
184
  ---
178
185
 
186
+ ### `pauseAll` / `resumeAll`
187
+
188
+ Drops the inner socket of every active provider that supports pausing (e.g. providers built via `createWsJsonRpcProvider`). Pooled clients and ref counts are preserved; tracked subscriptions are re-sent on `resumeAll()` via the replay wrapper.
189
+
190
+ Use this when the host process goes to background (mobile / OS suspend) and you want to release sockets without tearing down callers.
191
+
192
+ **Signature:**
193
+
194
+ ```ts
195
+ function pauseAll(): void
196
+ function resumeAll(): void
197
+ ```
198
+
199
+ **Example:**
200
+
201
+ ```ts
202
+ document.addEventListener('visibilitychange', () => {
203
+ if (document.visibilityState === 'hidden') {
204
+ chains.pauseAll();
205
+ } else {
206
+ chains.resumeAll();
207
+ }
208
+ });
209
+ ```
210
+
211
+ ---
212
+
179
213
  ### `createWsJsonRpcProvider(options)`
180
214
 
181
215
  WebSocket provider factory. Wraps polkadot-api's `getWsProvider` and translates WebSocket events to `ConnectionStatus`. Active JSON-RPC subscriptions are automatically replayed after a reconnect — consumers using `getProvider` don't need to handle reconnects manually.
182
216
 
217
+ The returned provider is **pausable**: `pause()` drops the inner socket and `resume()` reopens it. The connection pool calls these via `pauseAll()` / `resumeAll()`.
218
+
183
219
  **Signature:**
184
220
 
185
221
  ```ts
186
222
  function createWsJsonRpcProvider(options: {
187
223
  endpoints: string[];
188
224
  onStatusChanged?: (status: ConnectionStatus) => void;
189
- }): JsonRpcProvider;
225
+ websocketClass?: typeof WebSocket;
226
+ heartbeatTimeout?: number;
227
+ connectionTimeout?: number;
228
+ logger?: SocketLoggerFn;
229
+ }): PausableJsonRpcProvider;
230
+
231
+ type PausableJsonRpcProvider = JsonRpcProvider & {
232
+ pause(): void;
233
+ resume(): void;
234
+ };
190
235
  ```
191
236
 
237
+ | Field | Description |
238
+ |---|---|
239
+ | `endpoints` | One or more WebSocket URLs. Failover is handled by the underlying `getWsProvider`. |
240
+ | `onStatusChanged` | Optional. Called with `'connecting' \| 'connected' \| 'disconnected'` on socket events. |
241
+ | `websocketClass` | Optional. Override the WebSocket implementation (e.g. `ws` in Node). |
242
+ | `heartbeatTimeout` | Optional. Milliseconds without a server message before the socket is considered dead. Defaults to the underlying library's 40 s. |
243
+ | `connectionTimeout` | Optional. Milliseconds to wait for the initial connection before giving up. |
244
+ | `logger` | Optional. A `SocketLoggerFn` from `@polkadot-api/ws-provider` for tracing socket events. |
245
+
192
246
  **Example:**
193
247
 
194
248
  ```ts
@@ -226,11 +280,30 @@ import { createLocalStorageAdapter } from '@novasamatech/storage-adapter';
226
280
  const cache = createMetadataCache();
227
281
 
228
282
  // With localStorage persistence (survives page reloads)
229
- const cache = createMetadataCache({
283
+ const persistedCache = createMetadataCache({
230
284
  storage: createLocalStorageAdapter('chain-metadata'),
231
285
  });
232
286
  ```
233
287
 
288
+ ---
289
+
290
+ ### `withSubscriptionReplay(provider, onReconnect)`
291
+
292
+ Wraps any `JsonRpcProvider` so that active JSON-RPC subscriptions are automatically re-sent after the underlying transport reconnects. `createWsJsonRpcProvider` applies this internally — use it directly only when building a custom provider that needs the same behavior.
293
+
294
+ **Signature:**
295
+
296
+ ```ts
297
+ function withSubscriptionReplay(
298
+ provider: JsonRpcProvider,
299
+ onReconnect: (callback: VoidFunction) => VoidFunction,
300
+ ): JsonRpcProvider;
301
+ ```
302
+
303
+ `onReconnect` is a subscription primitive: call the supplied `callback` whenever your transport finishes reconnecting, and return a teardown function that removes the listener.
304
+
305
+ > **Note:** After a reconnect the server assigns new subscription IDs. Always unsubscribe with the most recently received ID — stale IDs from a previous connection silently fail.
306
+
234
307
  ## Recipes
235
308
 
236
309
  ### Custom resolve
@@ -241,12 +314,14 @@ The `resolve` callback transforms the raw `PolkadotClient` into whatever your ap
241
314
  import { type PolkadotClient, type TypedApi } from 'polkadot-api';
242
315
  import { dot, type DotDescriptor } from '@polkadot-api/descriptors';
243
316
 
317
+ type Chain = ChainConfig & { nodes: string[] };
318
+
244
319
  type ResolvedApi = {
245
320
  api: TypedApi<DotDescriptor>;
246
321
  client: PolkadotClient;
247
322
  };
248
323
 
249
- const chains = createChainConnection<ChainConfig, ResolvedApi>({
324
+ const chains = createChainConnection<Chain, ResolvedApi>({
250
325
  createProvider(chain, onStatusChanged) {
251
326
  return createWsJsonRpcProvider({
252
327
  endpoints: chain.nodes,
@@ -275,11 +350,13 @@ unlock();
275
350
  ```ts
276
351
  import { createLocalStorageAdapter } from '@novasamatech/storage-adapter';
277
352
 
353
+ type Chain = ChainConfig & { nodes: string[] };
354
+
278
355
  const metadataCache = createMetadataCache({
279
356
  storage: createLocalStorageAdapter('chain-metadata'),
280
357
  });
281
358
 
282
- const chains = createChainConnection({
359
+ const chains = createChainConnection<Chain>({
283
360
  createProvider: (chain, onStatusChanged) =>
284
361
  createWsJsonRpcProvider({
285
362
  endpoints: chain.nodes,
@@ -302,6 +379,7 @@ import { type Client as SmoldotClient, start as startSmoldot } from 'polkadot-ap
302
379
 
303
380
  type MyChain = ChainConfig & {
304
381
  name: string;
382
+ nodes: string[];
305
383
  lightClient?: boolean;
306
384
  };
307
385
 
@@ -361,11 +439,16 @@ Common additions beyond `api` and `client`:
361
439
 
362
440
  ```ts
363
441
  import { dot, ksm, type DotDescriptor, type KsmDescriptor } from '@polkadot-api/descriptors';
364
- import { type ChainDefinition, type CompatibilityToken, type TypedApi, getTypedCodecs } from 'polkadot-api';
442
+ import { type ChainDefinition, type CompatibilityToken, type PolkadotClient, type TypedApi, getTypedCodecs } from 'polkadot-api';
443
+
444
+ type Chain = ChainConfig & { nodes: string[] };
445
+
446
+ const POLKADOT_GENESIS = '0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3';
447
+ const KUSAMA_GENESIS = '0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe';
365
448
 
366
449
  const descriptorMap: Record<string, ChainDefinition> = {
367
- [polkadot.genesisHash]: dot,
368
- [kusama.genesisHash]: ksm,
450
+ [POLKADOT_GENESIS]: dot,
451
+ [KUSAMA_GENESIS]: ksm,
369
452
  };
370
453
 
371
454
  type ResolvedApi = {
@@ -375,7 +458,7 @@ type ResolvedApi = {
375
458
  compatibilityToken: CompatibilityToken;
376
459
  };
377
460
 
378
- const chains = createChainConnection<MyChain, ResolvedApi>({
461
+ const chains = createChainConnection<Chain, ResolvedApi>({
379
462
  createProvider: (chain, onStatusChanged) =>
380
463
  createWsJsonRpcProvider({
381
464
  endpoints: chain.nodes,
@@ -491,6 +574,7 @@ import { dot, dot_ah, dot_ppl, ksm, ksm_ah, wnd, wnd_ah } from '@polkadot-api/de
491
574
 
492
575
  type Chain = ChainConfig & {
493
576
  name: string;
577
+ nodes: string[];
494
578
  specName: string;
495
579
  };
496
580
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/host-substrate-chain-connection",
3
3
  "type": "module",
4
- "version": "0.7.5",
4
+ "version": "0.7.6",
5
5
  "description": "Chain connection pool with ref counting and provider branching for Polkadot API",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "README.md"
26
26
  ],
27
27
  "dependencies": {
28
- "@novasamatech/storage-adapter": "0.7.5",
28
+ "@novasamatech/storage-adapter": "0.7.6",
29
29
  "@polkadot-api/ws-provider": "^0.9.0",
30
30
  "@polkadot-api/json-rpc-provider": "^0.2.0",
31
31
  "@polkadot-api/json-rpc-provider-proxy": "^0.4.0",