@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.
- package/README.md +95 -11
- 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
|
-
|
|
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
|
-
|
|
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
|
|
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<
|
|
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
|
-
[
|
|
368
|
-
[
|
|
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<
|
|
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.
|
|
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.
|
|
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",
|