@parity/product-sdk-chain-client 0.1.0 → 0.2.0

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/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- // src/clients.ts
2
- import { createClient } from "polkadot-api";
1
+ import { createClient } from 'polkadot-api';
2
+ import { BULLETIN_RPCS, getHostProvider } from '@parity/product-sdk-host';
3
+ export { isInsideContainer, isInsideContainerSync } from '@parity/product-sdk-host';
3
4
 
4
- // src/providers.ts
5
- import { getHostProvider } from "@parity/product-sdk-host";
5
+ // src/clients.ts
6
6
  async function createProvider(genesisHash) {
7
7
  const hostProvider = await getHostProvider(genesisHash);
8
8
  if (!hostProvider) {
@@ -12,37 +12,6 @@ async function createProvider(genesisHash) {
12
12
  }
13
13
  return hostProvider;
14
14
  }
15
- if (void 0) {
16
- const { test, expect, vi, beforeEach } = void 0;
17
- const state = vi.hoisted(() => ({
18
- fakeProvider: (() => {
19
- }),
20
- hostProviderCalls: [],
21
- hostProviderAvailable: true
22
- }));
23
- vi.mock("@parity/product-sdk-host", async (importOriginal) => ({
24
- ...await importOriginal(),
25
- getHostProvider: async (...args) => {
26
- state.hostProviderCalls.push(args);
27
- if (!state.hostProviderAvailable) return null;
28
- return state.fakeProvider;
29
- }
30
- }));
31
- beforeEach(() => {
32
- state.hostProviderCalls = [];
33
- state.hostProviderAvailable = true;
34
- });
35
- test("returns host provider when available", async () => {
36
- const result = await createProvider("0xabc");
37
- expect(result).toBe(state.fakeProvider);
38
- expect(state.hostProviderCalls.length).toBe(1);
39
- expect(state.hostProviderCalls[0][0]).toBe("0xabc");
40
- });
41
- test("throws when host provider unavailable", async () => {
42
- state.hostProviderAvailable = false;
43
- await expect(createProvider("0xabc")).rejects.toThrow(/Host provider unavailable/);
44
- });
45
- }
46
15
 
47
16
  // src/hmr.ts
48
17
  function getClientCache() {
@@ -59,18 +28,6 @@ function clearClientCache() {
59
28
  }
60
29
  cache.clear();
61
30
  }
62
- if (void 0) {
63
- const { test, expect } = void 0;
64
- test("getClientCache returns a Map", () => {
65
- const cache = getClientCache();
66
- expect(cache).toBeInstanceOf(Map);
67
- });
68
- test("getClientCache returns the same instance on repeated calls", () => {
69
- const a = getClientCache();
70
- const b = getClientCache();
71
- expect(a).toBe(b);
72
- });
73
- }
74
31
 
75
32
  // src/clients.ts
76
33
  var cacheKey = (fingerprint, genesis) => `${fingerprint}:${genesis}`;
@@ -171,129 +128,6 @@ function isConnected(descriptor) {
171
128
  if (!genesis) return false;
172
129
  return findEntryByGenesis(genesis) !== void 0;
173
130
  }
174
- if (void 0) {
175
- let seedCache = function(genesis, client, fp = "test") {
176
- getClientCache().set(cacheKey(fp, genesis), {
177
- client,
178
- api: /* @__PURE__ */ new Map()
179
- });
180
- };
181
- seedCache2 = seedCache;
182
- const { test, expect, beforeEach } = void 0;
183
- const fakeDescriptor = { genesis: "0xtest" };
184
- const fakeClient = {
185
- destroy: () => {
186
- },
187
- getTypedApi: () => ({})
188
- };
189
- beforeEach(() => {
190
- clearClientCache();
191
- clientInstances.clear();
192
- });
193
- test("isConnected returns false for unknown chain", () => {
194
- expect(isConnected(fakeDescriptor)).toBe(false);
195
- });
196
- test("isConnected returns true after cache is populated", () => {
197
- seedCache("0xtest", fakeClient);
198
- expect(isConnected(fakeDescriptor)).toBe(true);
199
- });
200
- test("isConnected returns false for descriptor without genesis", () => {
201
- expect(isConnected({})).toBe(false);
202
- });
203
- test("getClient returns client from cache", () => {
204
- seedCache("0xtest", fakeClient);
205
- expect(getClient(fakeDescriptor)).toBe(fakeClient);
206
- });
207
- test("getClient throws for unconnected chain", () => {
208
- expect(() => getClient(fakeDescriptor)).toThrow(/Chain not connected/);
209
- });
210
- test("getClient throws for descriptor without genesis", () => {
211
- expect(() => getClient({})).toThrow(/no genesis hash/);
212
- });
213
- test("destroyAll calls client.destroy() and clears caches", () => {
214
- let destroyed = false;
215
- const trackableClient = {
216
- destroy: () => {
217
- destroyed = true;
218
- },
219
- getTypedApi: () => ({})
220
- };
221
- seedCache("0xtest", trackableClient);
222
- clientInstances.set("test", Promise.resolve({}));
223
- destroyAll();
224
- expect(destroyed).toBe(true);
225
- expect(isConnected(fakeDescriptor)).toBe(false);
226
- expect(clientInstances.size).toBe(0);
227
- });
228
- test("createChainClient returns same promise for identical config", async () => {
229
- const fakeResult = {};
230
- const fp = configFingerprint({ a: fakeDescriptor });
231
- clientInstances.set(fp, Promise.resolve(fakeResult));
232
- const result = await createChainClient({
233
- chains: { a: fakeDescriptor },
234
- rpcs: { a: [] }
235
- });
236
- expect(result).toBe(fakeResult);
237
- });
238
- test("createChainClient deduplicates concurrent calls", async () => {
239
- const fakeResult = {};
240
- const fp = configFingerprint({ x: fakeDescriptor });
241
- clientInstances.set(fp, Promise.resolve(fakeResult));
242
- const [a, b] = await Promise.all([
243
- createChainClient({ chains: { x: fakeDescriptor }, rpcs: { x: [] } }),
244
- createChainClient({ chains: { x: fakeDescriptor }, rpcs: { x: [] } })
245
- ]);
246
- expect(a).toBe(b);
247
- });
248
- test("createChainClient returns different results for different configs", async () => {
249
- const descA = { genesis: "0xaaa" };
250
- const descB = { genesis: "0xbbb" };
251
- const resultA = {};
252
- const resultB = {};
253
- clientInstances.set(configFingerprint({ a: descA }), Promise.resolve(resultA));
254
- clientInstances.set(configFingerprint({ b: descB }), Promise.resolve(resultB));
255
- const a = await createChainClient({ chains: { a: descA }, rpcs: { a: [] } });
256
- const b = await createChainClient({ chains: { b: descB }, rpcs: { b: [] } });
257
- expect(a).not.toBe(b);
258
- });
259
- test("configFingerprint is stable regardless of key order", () => {
260
- const d1 = { genesis: "0x1" };
261
- const d2 = { genesis: "0x2" };
262
- expect(configFingerprint({ a: d1, b: d2 })).toBe(configFingerprint({ b: d2, a: d1 }));
263
- });
264
- test("findEntryByGenesis returns undefined for missing genesis", () => {
265
- expect(findEntryByGenesis("0xnonexistent")).toBeUndefined();
266
- });
267
- test("full lifecycle: seed, verify connected, destroy, verify disconnected", () => {
268
- seedCache("0xtest", fakeClient);
269
- expect(isConnected(fakeDescriptor)).toBe(true);
270
- expect(getClient(fakeDescriptor)).toBe(fakeClient);
271
- destroyAll();
272
- expect(isConnected(fakeDescriptor)).toBe(false);
273
- expect(() => getClient(fakeDescriptor)).toThrow(/Chain not connected/);
274
- });
275
- test("two fingerprints cached independently, destroy one leaves other intact", () => {
276
- const sharedGenesis = "0xshared";
277
- const clientA = { destroy: () => {
278
- } };
279
- const clientB = { destroy: () => {
280
- } };
281
- const descriptorShared = { genesis: sharedGenesis };
282
- seedCache(sharedGenesis, clientA, "fpA");
283
- seedCache(sharedGenesis, clientB, "fpB");
284
- expect(isConnected(descriptorShared)).toBe(true);
285
- const cache = getClientCache();
286
- const keyA = cacheKey("fpA", sharedGenesis);
287
- cache.get(keyA)?.client.destroy();
288
- cache.delete(keyA);
289
- expect(isConnected(descriptorShared)).toBe(true);
290
- expect(getClient(descriptorShared)).toBe(clientB);
291
- });
292
- }
293
- var seedCache2;
294
-
295
- // src/presets.ts
296
- import { BULLETIN_RPCS } from "@parity/product-sdk-host";
297
131
  var AVAILABLE_ENVIRONMENTS = /* @__PURE__ */ new Set(["paseo"]);
298
132
  var rpcs = {
299
133
  polkadot: {
@@ -323,14 +157,14 @@ var rpcs = {
323
157
  };
324
158
  async function loadDescriptors(env) {
325
159
  const assetHubImport = {
326
- polkadot: () => import("@parity/product-sdk-descriptors/polkadot-asset-hub"),
327
- kusama: () => import("@parity/product-sdk-descriptors/kusama-asset-hub"),
328
- paseo: () => import("@parity/product-sdk-descriptors/paseo-asset-hub")
160
+ polkadot: () => import('@parity/product-sdk-descriptors/polkadot-asset-hub'),
161
+ kusama: () => import('@parity/product-sdk-descriptors/kusama-asset-hub'),
162
+ paseo: () => import('@parity/product-sdk-descriptors/paseo-asset-hub')
329
163
  }[env]();
330
164
  const [ahMod, { bulletin }, { individuality }] = await Promise.all([
331
165
  assetHubImport,
332
- import("@parity/product-sdk-descriptors/bulletin"),
333
- import("@parity/product-sdk-descriptors/individuality")
166
+ import('@parity/product-sdk-descriptors/bulletin'),
167
+ import('@parity/product-sdk-descriptors/individuality')
334
168
  ]);
335
169
  const assetHub = "polkadot_asset_hub" in ahMod ? ahMod.polkadot_asset_hub : "kusama_asset_hub" in ahMod ? ahMod.kusama_asset_hub : ahMod.paseo_asset_hub;
336
170
  return { assetHub, bulletin, individuality };
@@ -354,75 +188,7 @@ async function getChainAPI(env) {
354
188
  }
355
189
  });
356
190
  }
357
- if (void 0) {
358
- const { test, expect, beforeEach } = void 0;
359
- const { destroyAll: destroyAll2 } = await null;
360
- const GENESIS = {
361
- polkadot_asset_hub: "0x68d56f15f85d3136970ec16946040bc1752654e906147f7e43e9d539d7c3de2f",
362
- kusama_asset_hub: "0x48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a",
363
- paseo_asset_hub: "0xd6eec26135305a8ad257a20d003357284c8aa03d0bdb2b357ab0a22371e11ef2",
364
- bulletin: "0x744960c32e3a3df5440e1ecd4d34096f1ce2230d7016a5ada8a765d5a622b4ea",
365
- individuality: "0xd01475fde5d0592989b7715ae1d2e89fdb4f8c7688c09c850d75e1d4bdb47d64"
366
- };
367
- beforeEach(() => {
368
- destroyAll2();
369
- });
370
- test("genesis constants are valid hex hashes", () => {
371
- for (const hash of Object.values(GENESIS)) {
372
- expect(hash).toMatch(/^0x[a-f0-9]{64}$/);
373
- }
374
- });
375
- test("rpcs defined for all environments", () => {
376
- for (const env of ["polkadot", "kusama", "paseo"]) {
377
- const envRpcs = rpcs[env];
378
- expect(envRpcs.assetHub.length).toBeGreaterThan(0);
379
- }
380
- });
381
- test("paseo has RPCs for all chains", () => {
382
- const envRpcs = rpcs.paseo;
383
- expect(envRpcs.bulletin.length).toBeGreaterThan(0);
384
- expect(envRpcs.individuality.length).toBeGreaterThan(0);
385
- });
386
- test("polkadot and kusama throw as not yet available", async () => {
387
- await expect(getChainAPI("polkadot")).rejects.toThrow("not yet available");
388
- await expect(getChainAPI("kusama")).rejects.toThrow("not yet available");
389
- });
390
- test("loadDescriptors returns descriptors with genesis hashes for paseo", async () => {
391
- const descriptors = await loadDescriptors("paseo");
392
- expect(descriptors).toBeDefined();
393
- expect(descriptors.assetHub).toBeDefined();
394
- expect(descriptors.bulletin).toBeDefined();
395
- expect(descriptors.individuality).toBeDefined();
396
- expect(descriptors.assetHub.genesis).toBe(GENESIS.paseo_asset_hub);
397
- expect(descriptors.bulletin.genesis).toBe(GENESIS.bulletin);
398
- expect(descriptors.individuality.genesis).toBe(GENESIS.individuality);
399
- });
400
- test("loadDescriptors returns correct asset hub per environment", async () => {
401
- const polkadot = await loadDescriptors("polkadot");
402
- const kusama = await loadDescriptors("kusama");
403
- const paseo = await loadDescriptors("paseo");
404
- expect(polkadot.assetHub.genesis).toBe(GENESIS.polkadot_asset_hub);
405
- expect(kusama.assetHub.genesis).toBe(GENESIS.kusama_asset_hub);
406
- expect(paseo.assetHub.genesis).toBe(GENESIS.paseo_asset_hub);
407
- expect(polkadot.bulletin.genesis).toBe(paseo.bulletin.genesis);
408
- expect(polkadot.individuality.genesis).toBe(paseo.individuality.genesis);
409
- });
410
- test("only paseo is currently available", () => {
411
- expect(AVAILABLE_ENVIRONMENTS.has("paseo")).toBe(true);
412
- expect(AVAILABLE_ENVIRONMENTS.has("polkadot")).toBe(false);
413
- expect(AVAILABLE_ENVIRONMENTS.has("kusama")).toBe(false);
414
- });
415
- }
416
191
 
417
- // src/index.ts
418
- import { isInsideContainer, isInsideContainerSync } from "@parity/product-sdk-host";
419
- export {
420
- createChainClient,
421
- destroyAll,
422
- getChainAPI,
423
- getClient,
424
- isConnected,
425
- isInsideContainer,
426
- isInsideContainerSync
427
- };
192
+ export { createChainClient, destroyAll, getChainAPI, getClient, isConnected };
193
+ //# sourceMappingURL=index.js.map
428
194
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/clients.ts","../src/providers.ts","../src/hmr.ts","../src/presets.ts","../src/index.ts"],"sourcesContent":["import type { ChainDefinition, PolkadotClient } from \"polkadot-api\";\nimport { createClient } from \"polkadot-api\";\nimport { createProvider } from \"./providers.js\";\nimport { getClientCache, clearClientCache } from \"./hmr.js\";\nimport type { ChainEntry, ChainClientConfig, ChainClient } from \"./types.js\";\n\n// Cache keys are scoped by a fingerprint of the config so that two\n// `createChainClient` calls with different chain sets don't collide.\nconst cacheKey = (fingerprint: string, genesis: string) => `${fingerprint}:${genesis}`;\n\nfunction findEntryByGenesis(genesis: string): ChainEntry | undefined {\n for (const [key, entry] of getClientCache()) {\n if (key.endsWith(`:${genesis}`)) return entry;\n }\n}\n\nconst clientInstances = new Map<string, Promise<ChainClient<any>>>();\n\n/** Build a stable fingerprint from sorted chain names + genesis hashes. */\nfunction configFingerprint(chains: Record<string, ChainDefinition>): string {\n return Object.entries(chains)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, desc]) => `${name}:${desc.genesis ?? \"unknown\"}`)\n .join(\"|\");\n}\n\n/**\n * Create a multi-chain client with user-provided descriptors and RPC endpoints.\n *\n * Returns fully-typed APIs for each chain plus raw `PolkadotClient` access via `.raw`.\n * Connections use host routing (via `@parity/product-sdk-host`) when inside a container,\n * falling back to direct WebSocket RPC.\n *\n * Results are cached by genesis-hash fingerprint — calling with the same descriptors\n * returns the same instance.\n *\n * @example\n * ```ts\n * import { createChainClient } from \"@parity/product-sdk-chain-client\";\n * import { paseo_asset_hub } from \"./descriptors/paseo-asset-hub\";\n * import { bulletin } from \"./descriptors/bulletin\";\n *\n * const client = await createChainClient({\n * chains: { assetHub: paseo_asset_hub, bulletin },\n * rpcs: {\n * assetHub: [\"wss://sys.ibp.network/asset-hub-paseo\"],\n * bulletin: [\"wss://paseo-bulletin-rpc.polkadot.io\"],\n * },\n * });\n *\n * // Fully typed from your descriptors\n * const account = await client.assetHub.query.System.Account.getValue(addr);\n * const fee = await client.bulletin.query.TransactionStorage.ByteFee.getValue();\n *\n * // Raw client for advanced use (e.g., InkSdk for contracts)\n * import { createInkSdk } from \"@polkadot-api/sdk-ink\";\n * const inkSdk = createInkSdk(client.raw.assetHub, { atBest: true });\n *\n * // Cleanup\n * client.destroy();\n * ```\n */\nexport async function createChainClient<const TChains extends Record<string, ChainDefinition>>(\n config: ChainClientConfig<TChains>,\n): Promise<ChainClient<TChains>> {\n const fingerprint = configFingerprint(config.chains);\n\n const existing = clientInstances.get(fingerprint);\n if (existing) return existing as Promise<ChainClient<TChains>>;\n\n const promise = initChainClient(config, fingerprint).catch((err) => {\n // Clean up any clients created before the failure to avoid leaking\n // WebSocket connections that are unreachable except via destroyAll().\n const cache = getClientCache();\n for (const [key, entry] of cache) {\n if (key.startsWith(`${fingerprint}:`)) {\n try {\n entry.client.destroy();\n } catch {\n /* already destroyed */\n }\n cache.delete(key);\n }\n }\n clientInstances.delete(fingerprint);\n throw err;\n });\n clientInstances.set(fingerprint, promise);\n return promise;\n}\n\n/* @integration */\nasync function initChainClient<const TChains extends Record<string, ChainDefinition>>(\n config: ChainClientConfig<TChains>,\n fingerprint: string,\n): Promise<ChainClient<TChains>> {\n const names = Object.keys(config.chains) as (string & keyof TChains)[];\n const clientCache = getClientCache();\n\n // Create providers and clients in parallel\n const entries = await Promise.all(\n names.map(async (name) => {\n const descriptor = config.chains[name] as ChainDefinition;\n const genesis = descriptor.genesis;\n if (!genesis) {\n throw new Error(`Descriptor for chain \"${name}\" has no genesis hash.`);\n }\n const provider = await createProvider(genesis);\n const client = createClient(provider);\n\n // Populate HMR cache so getClient() and isConnected() work\n const key = cacheKey(fingerprint, genesis);\n if (!clientCache.has(key)) {\n clientCache.set(key, {\n client,\n api: new Map(),\n } satisfies ChainEntry);\n }\n\n return { name, descriptor, client, genesis };\n }),\n );\n\n // Build typed APIs and raw client map\n const apis = {} as Record<string, unknown>;\n const raw = {} as Record<string, PolkadotClient>;\n\n for (const { name, descriptor, client } of entries) {\n apis[name] = client.getTypedApi(descriptor);\n raw[name] = client;\n }\n\n return {\n ...apis,\n raw,\n destroy() {\n for (const { genesis } of entries) {\n const key = cacheKey(fingerprint, genesis);\n const entry = clientCache.get(key);\n if (entry) {\n try {\n entry.client.destroy();\n } catch {\n /* already destroyed */\n }\n clientCache.delete(key);\n }\n }\n clientInstances.delete(fingerprint);\n },\n } as ChainClient<TChains>;\n}\n\n/**\n * Destroy all chain client instances and reset internal caches.\n *\n * Tears down every connection created by {@link createChainClient}.\n */\nexport function destroyAll(): void {\n clearClientCache();\n clientInstances.clear();\n}\n\n/**\n * Get the raw `PolkadotClient` for a connected chain by its descriptor.\n *\n * The chain must have been initialized via {@link createChainClient} first.\n * Alternatively, use `client.raw.<name>` on the returned {@link ChainClient}.\n *\n * @throws If the chain has not been connected yet.\n */\nexport function getClient(descriptor: ChainDefinition): PolkadotClient {\n const genesis = descriptor.genesis;\n if (!genesis) throw new Error(\"Descriptor has no genesis hash.\");\n const entry = findEntryByGenesis(genesis);\n if (!entry?.client) {\n throw new Error(\n `Chain not connected (genesis: ${genesis}). Call createChainClient() first to establish connections.`,\n );\n }\n return entry.client;\n}\n\n/**\n * Check if a chain is currently connected.\n *\n * Synchronous — no side effects, no initialization.\n */\nexport function isConnected(descriptor: ChainDefinition): boolean {\n const genesis = descriptor.genesis;\n if (!genesis) return false;\n return findEntryByGenesis(genesis) !== undefined;\n}\n\nif (import.meta.vitest) {\n const { test, expect, beforeEach } = import.meta.vitest;\n\n const fakeDescriptor = { genesis: \"0xtest\" } as ChainDefinition;\n const fakeClient = {\n destroy: () => {},\n getTypedApi: () => ({}),\n } as unknown as PolkadotClient;\n\n function seedCache(genesis: string, client: PolkadotClient, fp = \"test\") {\n getClientCache().set(cacheKey(fp, genesis), {\n client,\n api: new Map(),\n });\n }\n\n beforeEach(() => {\n clearClientCache();\n clientInstances.clear();\n });\n\n // --- isConnected ---\n\n test(\"isConnected returns false for unknown chain\", () => {\n expect(isConnected(fakeDescriptor)).toBe(false);\n });\n\n test(\"isConnected returns true after cache is populated\", () => {\n seedCache(\"0xtest\", fakeClient);\n expect(isConnected(fakeDescriptor)).toBe(true);\n });\n\n test(\"isConnected returns false for descriptor without genesis\", () => {\n expect(isConnected({} as ChainDefinition)).toBe(false);\n });\n\n // --- getClient ---\n\n test(\"getClient returns client from cache\", () => {\n seedCache(\"0xtest\", fakeClient);\n expect(getClient(fakeDescriptor)).toBe(fakeClient);\n });\n\n test(\"getClient throws for unconnected chain\", () => {\n expect(() => getClient(fakeDescriptor)).toThrow(/Chain not connected/);\n });\n\n test(\"getClient throws for descriptor without genesis\", () => {\n expect(() => getClient({} as ChainDefinition)).toThrow(/no genesis hash/);\n });\n\n // --- destroyAll ---\n\n test(\"destroyAll calls client.destroy() and clears caches\", () => {\n let destroyed = false;\n const trackableClient = {\n destroy: () => {\n destroyed = true;\n },\n getTypedApi: () => ({}),\n } as unknown as PolkadotClient;\n seedCache(\"0xtest\", trackableClient);\n clientInstances.set(\"test\", Promise.resolve({} as ChainClient<any>));\n destroyAll();\n expect(destroyed).toBe(true);\n expect(isConnected(fakeDescriptor)).toBe(false);\n expect(clientInstances.size).toBe(0);\n });\n\n // --- createChainClient ---\n\n test(\"createChainClient returns same promise for identical config\", async () => {\n const fakeResult = {} as ChainClient<any>;\n const fp = configFingerprint({ a: fakeDescriptor });\n clientInstances.set(fp, Promise.resolve(fakeResult));\n const result = await createChainClient({\n chains: { a: fakeDescriptor },\n rpcs: { a: [] },\n });\n expect(result).toBe(fakeResult);\n });\n\n test(\"createChainClient deduplicates concurrent calls\", async () => {\n const fakeResult = {} as ChainClient<any>;\n const fp = configFingerprint({ x: fakeDescriptor });\n clientInstances.set(fp, Promise.resolve(fakeResult));\n const [a, b] = await Promise.all([\n createChainClient({ chains: { x: fakeDescriptor }, rpcs: { x: [] } }),\n createChainClient({ chains: { x: fakeDescriptor }, rpcs: { x: [] } }),\n ]);\n expect(a).toBe(b);\n });\n\n test(\"createChainClient returns different results for different configs\", async () => {\n const descA = { genesis: \"0xaaa\" } as ChainDefinition;\n const descB = { genesis: \"0xbbb\" } as ChainDefinition;\n const resultA = {} as ChainClient<any>;\n const resultB = {} as ChainClient<any>;\n clientInstances.set(configFingerprint({ a: descA }), Promise.resolve(resultA));\n clientInstances.set(configFingerprint({ b: descB }), Promise.resolve(resultB));\n const a = await createChainClient({ chains: { a: descA }, rpcs: { a: [] } });\n const b = await createChainClient({ chains: { b: descB }, rpcs: { b: [] } });\n expect(a).not.toBe(b);\n });\n\n // --- configFingerprint ---\n\n test(\"configFingerprint is stable regardless of key order\", () => {\n const d1 = { genesis: \"0x1\" } as ChainDefinition;\n const d2 = { genesis: \"0x2\" } as ChainDefinition;\n expect(configFingerprint({ a: d1, b: d2 })).toBe(configFingerprint({ b: d2, a: d1 }));\n });\n\n // --- findEntryByGenesis ---\n\n test(\"findEntryByGenesis returns undefined for missing genesis\", () => {\n expect(findEntryByGenesis(\"0xnonexistent\")).toBeUndefined();\n });\n\n // --- full lifecycle ---\n\n test(\"full lifecycle: seed, verify connected, destroy, verify disconnected\", () => {\n seedCache(\"0xtest\", fakeClient);\n expect(isConnected(fakeDescriptor)).toBe(true);\n expect(getClient(fakeDescriptor)).toBe(fakeClient);\n destroyAll();\n expect(isConnected(fakeDescriptor)).toBe(false);\n expect(() => getClient(fakeDescriptor)).toThrow(/Chain not connected/);\n });\n\n test(\"two fingerprints cached independently, destroy one leaves other intact\", () => {\n const sharedGenesis = \"0xshared\";\n const clientA = { destroy: () => {} } as PolkadotClient;\n const clientB = { destroy: () => {} } as PolkadotClient;\n const descriptorShared = { genesis: sharedGenesis } as ChainDefinition;\n\n seedCache(sharedGenesis, clientA, \"fpA\");\n seedCache(sharedGenesis, clientB, \"fpB\");\n\n expect(isConnected(descriptorShared)).toBe(true);\n\n // Destroy only fpA's entry\n const cache = getClientCache();\n const keyA = cacheKey(\"fpA\", sharedGenesis);\n cache.get(keyA)?.client.destroy();\n cache.delete(keyA);\n\n // fpB's entry still alive\n expect(isConnected(descriptorShared)).toBe(true);\n expect(getClient(descriptorShared)).toBe(clientB);\n });\n}\n","import { getHostProvider } from \"@parity/product-sdk-host\";\nimport type { JsonRpcProvider } from \"polkadot-api/ws-provider/web\";\n\n/**\n * Create a PAPI-compatible JSON-RPC provider for a chain.\n *\n * Routes connections through the host provider (`@parity/product-sdk-host`).\n * The SDK is designed to run exclusively inside a host container.\n *\n * @throws {Error} If the host provider is unavailable (not inside a container).\n */\nexport async function createProvider(genesisHash: string): Promise<JsonRpcProvider> {\n const hostProvider = await getHostProvider(genesisHash as `0x${string}`);\n if (!hostProvider) {\n throw new Error(\n `Host provider unavailable for chain ${genesisHash}. Ensure you are running inside a host container (Polkadot Browser / Desktop).`,\n );\n }\n return hostProvider;\n}\n\nif (import.meta.vitest) {\n const { test, expect, vi, beforeEach } = import.meta.vitest;\n\n // Shared state between hoisted mocks and tests\n const state = vi.hoisted(() => ({\n fakeProvider: (() => {}) as unknown as JsonRpcProvider,\n hostProviderCalls: [] as unknown[][],\n hostProviderAvailable: true,\n }));\n\n vi.mock(\"@parity/product-sdk-host\", async (importOriginal) => ({\n ...(await importOriginal<typeof import(\"@parity/product-sdk-host\")>()),\n getHostProvider: async (...args: unknown[]) => {\n state.hostProviderCalls.push(args);\n if (!state.hostProviderAvailable) return null;\n return state.fakeProvider;\n },\n }));\n\n beforeEach(() => {\n state.hostProviderCalls = [];\n state.hostProviderAvailable = true;\n });\n\n test(\"returns host provider when available\", async () => {\n const result = await createProvider(\"0xabc\");\n expect(result).toBe(state.fakeProvider);\n expect(state.hostProviderCalls.length).toBe(1);\n expect(state.hostProviderCalls[0][0]).toBe(\"0xabc\");\n });\n\n test(\"throws when host provider unavailable\", async () => {\n state.hostProviderAvailable = false;\n await expect(createProvider(\"0xabc\")).rejects.toThrow(/Host provider unavailable/);\n });\n}\n","import type { ChainEntry } from \"./types.js\";\n\ndeclare global {\n var __chainClientCache: Map<string, ChainEntry> | undefined;\n}\n\n/** Get the HMR-safe client cache, keyed by genesis hash. */\nexport function getClientCache(): Map<string, ChainEntry> {\n globalThis.__chainClientCache ??= new Map();\n return globalThis.__chainClientCache;\n}\n\n/** Clear all entries from the client cache. Destroys active clients. */\nexport function clearClientCache(): void {\n const cache = getClientCache();\n for (const entry of cache.values()) {\n try {\n entry.client.destroy();\n } catch {\n // client may already be destroyed\n }\n }\n cache.clear();\n}\n\nif (import.meta.vitest) {\n const { test, expect } = import.meta.vitest;\n\n test(\"getClientCache returns a Map\", () => {\n const cache = getClientCache();\n expect(cache).toBeInstanceOf(Map);\n });\n\n test(\"getClientCache returns the same instance on repeated calls\", () => {\n const a = getClientCache();\n const b = getClientCache();\n expect(a).toBe(b);\n });\n}\n","import type { ChainDefinition } from \"polkadot-api\";\nimport { BULLETIN_RPCS } from \"@parity/product-sdk-host\";\nimport { createChainClient } from \"./clients.js\";\nimport type { ChainClient } from \"./types.js\";\n\n// Type-only imports — erased at compile time, zero bundle cost.\n// These give us per-chain TypedApi types without importing runtime descriptor data.\nimport type { polkadot_asset_hub as PolkadotAssetHubDef } from \"@parity/product-sdk-descriptors/polkadot-asset-hub\";\nimport type { kusama_asset_hub as KusamaAssetHubDef } from \"@parity/product-sdk-descriptors/kusama-asset-hub\";\nimport type { paseo_asset_hub as PaseoAssetHubDef } from \"@parity/product-sdk-descriptors/paseo-asset-hub\";\nimport type { bulletin as BulletinDef } from \"@parity/product-sdk-descriptors/bulletin\";\nimport type { individuality as IndividualityDef } from \"@parity/product-sdk-descriptors/individuality\";\n\n/** Known network environment with built-in descriptors and RPC endpoints. */\nexport type Environment = \"polkadot\" | \"kusama\" | \"paseo\";\n\n/** Environments where all chains (asset hub, bulletin, individuality) are live. */\nconst AVAILABLE_ENVIRONMENTS: Set<Environment> = new Set([\"paseo\"]);\n\nconst rpcs = {\n polkadot: {\n assetHub: [\n \"wss://polkadot-asset-hub-rpc.polkadot.io\",\n \"wss://sys.ibp.network/asset-hub-polkadot\",\n ],\n bulletin: [...BULLETIN_RPCS.polkadot],\n individuality: [] as string[],\n },\n kusama: {\n assetHub: [\n \"wss://kusama-asset-hub-rpc.polkadot.io\",\n \"wss://sys.ibp.network/asset-hub-kusama\",\n ],\n bulletin: [...BULLETIN_RPCS.kusama],\n individuality: [] as string[],\n },\n paseo: {\n assetHub: [\n \"wss://asset-hub-paseo-rpc.n.dwellir.com\",\n \"wss://sys.ibp.network/asset-hub-paseo\",\n ],\n bulletin: [...BULLETIN_RPCS.paseo],\n individuality: [\"wss://paseo-people-next-rpc.polkadot.io\"],\n },\n} as const;\n\n/**\n * Lazy-load descriptors for a specific environment.\n * Only imports the chains needed — avoids bundling all 5 chains when\n * a consumer only uses one environment.\n */\nasync function loadDescriptors(env: Environment) {\n const assetHubImport = {\n polkadot: () => import(\"@parity/product-sdk-descriptors/polkadot-asset-hub\"),\n kusama: () => import(\"@parity/product-sdk-descriptors/kusama-asset-hub\"),\n paseo: () => import(\"@parity/product-sdk-descriptors/paseo-asset-hub\"),\n }[env]();\n\n const [ahMod, { bulletin }, { individuality }] = await Promise.all([\n assetHubImport,\n import(\"@parity/product-sdk-descriptors/bulletin\"),\n import(\"@parity/product-sdk-descriptors/individuality\"),\n ]);\n\n // Extract the asset hub descriptor (the named export varies per environment)\n const assetHub =\n \"polkadot_asset_hub\" in ahMod\n ? ahMod.polkadot_asset_hub\n : \"kusama_asset_hub\" in ahMod\n ? ahMod.kusama_asset_hub\n : (ahMod as typeof import(\"@parity/product-sdk-descriptors/paseo-asset-hub\"))\n .paseo_asset_hub;\n\n return { assetHub, bulletin, individuality };\n}\n\n/** Maps each environment to its asset hub descriptor type. */\ntype AssetHubDescriptors = {\n polkadot: typeof PolkadotAssetHubDef;\n kusama: typeof KusamaAssetHubDef;\n paseo: typeof PaseoAssetHubDef;\n};\n\n/** The chain shape returned by {@link getChainAPI} for a given environment. */\nexport type PresetChains<E extends Environment> = {\n assetHub: AssetHubDescriptors[E];\n bulletin: typeof BulletinDef;\n individuality: typeof IndividualityDef;\n};\n\n/**\n * Get a chain client for a known environment with built-in descriptors and RPCs.\n *\n * This is the **zero-config** path — no need to import descriptors or specify\n * endpoints. For custom chains or BYOD descriptors, use\n * {@link createChainClient} instead.\n *\n * Returns the same {@link ChainClient} type as `createChainClient`, with\n * `assetHub`, `bulletin`, and `individuality` chain keys.\n *\n * @example\n * ```ts\n * import { getChainAPI } from \"@parity/product-sdk-chain-client\";\n *\n * const client = await getChainAPI(\"paseo\");\n *\n * // Fully typed — no descriptor imports needed\n * const account = await client.assetHub.query.System.Account.getValue(addr);\n * const fee = await client.bulletin.query.TransactionStorage.ByteFee.getValue();\n *\n * // Raw client for advanced use (e.g., InkSdk for contracts)\n * import { createInkSdk } from \"@polkadot-api/sdk-ink\";\n * const inkSdk = createInkSdk(client.raw.assetHub, { atBest: true });\n *\n * client.destroy();\n * ```\n */\nexport async function getChainAPI<E extends Environment>(\n env: E,\n): Promise<ChainClient<PresetChains<E>>> {\n if (!AVAILABLE_ENVIRONMENTS.has(env)) {\n throw new Error(`Chain API for \"${env}\" is not yet available`);\n }\n\n const descriptors = await loadDescriptors(env);\n const envRpcs = rpcs[env];\n\n return createChainClient({\n chains: {\n assetHub: descriptors.assetHub,\n bulletin: descriptors.bulletin,\n individuality: descriptors.individuality,\n },\n rpcs: {\n assetHub: [...envRpcs.assetHub],\n bulletin: [...envRpcs.bulletin],\n individuality: [...envRpcs.individuality],\n },\n }) as Promise<ChainClient<PresetChains<E>>>;\n}\n\nif (import.meta.vitest) {\n const { test, expect, beforeEach } = import.meta.vitest;\n const { destroyAll } = await import(\"./clients.js\");\n\n // Test-only genesis hashes for assertion — not used in production code.\n const GENESIS = {\n polkadot_asset_hub: \"0x68d56f15f85d3136970ec16946040bc1752654e906147f7e43e9d539d7c3de2f\",\n kusama_asset_hub: \"0x48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a\",\n paseo_asset_hub: \"0xd6eec26135305a8ad257a20d003357284c8aa03d0bdb2b357ab0a22371e11ef2\",\n bulletin: \"0x744960c32e3a3df5440e1ecd4d34096f1ce2230d7016a5ada8a765d5a622b4ea\",\n individuality: \"0xd01475fde5d0592989b7715ae1d2e89fdb4f8c7688c09c850d75e1d4bdb47d64\",\n } as const;\n\n beforeEach(() => {\n destroyAll();\n });\n\n // --- GENESIS constants ---\n\n test(\"genesis constants are valid hex hashes\", () => {\n for (const hash of Object.values(GENESIS)) {\n expect(hash).toMatch(/^0x[a-f0-9]{64}$/);\n }\n });\n\n // --- RPC config ---\n\n test(\"rpcs defined for all environments\", () => {\n for (const env of [\"polkadot\", \"kusama\", \"paseo\"] as const) {\n const envRpcs = rpcs[env];\n expect(envRpcs.assetHub.length).toBeGreaterThan(0);\n }\n });\n\n test(\"paseo has RPCs for all chains\", () => {\n const envRpcs = rpcs.paseo;\n expect(envRpcs.bulletin.length).toBeGreaterThan(0);\n expect(envRpcs.individuality.length).toBeGreaterThan(0);\n });\n\n // --- getChainAPI ---\n\n test(\"polkadot and kusama throw as not yet available\", async () => {\n await expect(getChainAPI(\"polkadot\")).rejects.toThrow(\"not yet available\");\n await expect(getChainAPI(\"kusama\")).rejects.toThrow(\"not yet available\");\n });\n\n // --- loadDescriptors ---\n\n test(\"loadDescriptors returns descriptors with genesis hashes for paseo\", async () => {\n const descriptors = await loadDescriptors(\"paseo\");\n expect(descriptors).toBeDefined();\n expect(descriptors.assetHub).toBeDefined();\n expect(descriptors.bulletin).toBeDefined();\n expect(descriptors.individuality).toBeDefined();\n expect(descriptors.assetHub.genesis).toBe(GENESIS.paseo_asset_hub);\n expect(descriptors.bulletin.genesis).toBe(GENESIS.bulletin);\n expect(descriptors.individuality.genesis).toBe(GENESIS.individuality);\n });\n\n test(\"loadDescriptors returns correct asset hub per environment\", async () => {\n const polkadot = await loadDescriptors(\"polkadot\");\n const kusama = await loadDescriptors(\"kusama\");\n const paseo = await loadDescriptors(\"paseo\");\n expect(polkadot.assetHub.genesis).toBe(GENESIS.polkadot_asset_hub);\n expect(kusama.assetHub.genesis).toBe(GENESIS.kusama_asset_hub);\n expect(paseo.assetHub.genesis).toBe(GENESIS.paseo_asset_hub);\n // bulletin and individuality are the same across environments\n expect(polkadot.bulletin.genesis).toBe(paseo.bulletin.genesis);\n expect(polkadot.individuality.genesis).toBe(paseo.individuality.genesis);\n });\n\n // --- AVAILABLE_ENVIRONMENTS ---\n\n test(\"only paseo is currently available\", () => {\n expect(AVAILABLE_ENVIRONMENTS.has(\"paseo\")).toBe(true);\n expect(AVAILABLE_ENVIRONMENTS.has(\"polkadot\")).toBe(false);\n expect(AVAILABLE_ENVIRONMENTS.has(\"kusama\")).toBe(false);\n });\n}\n","// Core BYOD API — zero descriptor overhead\nexport { createChainClient, destroyAll, getClient, isConnected } from \"./clients.js\";\n\n// Preset environments — zero-config path with built-in descriptors\nexport { getChainAPI } from \"./presets.js\";\nexport type { Environment, PresetChains } from \"./presets.js\";\n\n// Types\nexport type { ChainClient, ChainClientConfig, ChainEntry } from \"./types.js\";\n\n// Re-export from host\nexport { isInsideContainer, isInsideContainerSync } from \"@parity/product-sdk-host\";\n"],"mappings":"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","names":["seedCache","destroyAll"]}
1
+ {"version":3,"sources":["../src/providers.ts","../src/hmr.ts","../src/clients.ts","../src/presets.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { getHostProvider } from \"@parity/product-sdk-host\";\nimport type { JsonRpcProvider } from \"polkadot-api\";\n\n/**\n * Create a PAPI-compatible JSON-RPC provider for a chain.\n *\n * Routes connections through the host provider (`@parity/product-sdk-host`).\n * The SDK is designed to run exclusively inside a host container.\n *\n * @throws {Error} If the host provider is unavailable (not inside a container).\n */\nexport async function createProvider(genesisHash: string): Promise<JsonRpcProvider> {\n const hostProvider = await getHostProvider(genesisHash as `0x${string}`);\n if (!hostProvider) {\n throw new Error(\n `Host provider unavailable for chain ${genesisHash}. Ensure you are running inside a host container (Polkadot Browser / Desktop).`,\n );\n }\n return hostProvider;\n}\n\nif (import.meta.vitest) {\n const { test, expect, vi, beforeEach } = import.meta.vitest;\n\n // Shared state between hoisted mocks and tests\n const state = vi.hoisted(() => ({\n fakeProvider: (() => {}) as unknown as JsonRpcProvider,\n hostProviderCalls: [] as unknown[][],\n hostProviderAvailable: true,\n }));\n\n vi.mock(\"@parity/product-sdk-host\", async (importOriginal) => ({\n ...(await importOriginal<typeof import(\"@parity/product-sdk-host\")>()),\n getHostProvider: async (...args: unknown[]) => {\n state.hostProviderCalls.push(args);\n if (!state.hostProviderAvailable) return null;\n return state.fakeProvider;\n },\n }));\n\n beforeEach(() => {\n state.hostProviderCalls = [];\n state.hostProviderAvailable = true;\n });\n\n test(\"returns host provider when available\", async () => {\n const result = await createProvider(\"0xabc\");\n expect(result).toBe(state.fakeProvider);\n expect(state.hostProviderCalls.length).toBe(1);\n expect(state.hostProviderCalls[0][0]).toBe(\"0xabc\");\n });\n\n test(\"throws when host provider unavailable\", async () => {\n state.hostProviderAvailable = false;\n await expect(createProvider(\"0xabc\")).rejects.toThrow(/Host provider unavailable/);\n });\n}\n","import type { ChainEntry } from \"./types.js\";\n\ndeclare global {\n var __chainClientCache: Map<string, ChainEntry> | undefined;\n}\n\n/** Get the HMR-safe client cache, keyed by genesis hash. */\nexport function getClientCache(): Map<string, ChainEntry> {\n globalThis.__chainClientCache ??= new Map();\n return globalThis.__chainClientCache;\n}\n\n/** Clear all entries from the client cache. Destroys active clients. */\nexport function clearClientCache(): void {\n const cache = getClientCache();\n for (const entry of cache.values()) {\n try {\n entry.client.destroy();\n } catch {\n // client may already be destroyed\n }\n }\n cache.clear();\n}\n\nif (import.meta.vitest) {\n const { test, expect } = import.meta.vitest;\n\n test(\"getClientCache returns a Map\", () => {\n const cache = getClientCache();\n expect(cache).toBeInstanceOf(Map);\n });\n\n test(\"getClientCache returns the same instance on repeated calls\", () => {\n const a = getClientCache();\n const b = getClientCache();\n expect(a).toBe(b);\n });\n}\n","import type { ChainDefinition, PolkadotClient } from \"polkadot-api\";\nimport { createClient } from \"polkadot-api\";\nimport { createProvider } from \"./providers.js\";\nimport { getClientCache, clearClientCache } from \"./hmr.js\";\nimport type { ChainEntry, ChainClientConfig, ChainClient } from \"./types.js\";\n\n// Cache keys are scoped by a fingerprint of the config so that two\n// `createChainClient` calls with different chain sets don't collide.\nconst cacheKey = (fingerprint: string, genesis: string) => `${fingerprint}:${genesis}`;\n\nfunction findEntryByGenesis(genesis: string): ChainEntry | undefined {\n for (const [key, entry] of getClientCache()) {\n if (key.endsWith(`:${genesis}`)) return entry;\n }\n}\n\nconst clientInstances = new Map<string, Promise<ChainClient<any>>>();\n\n/** Build a stable fingerprint from sorted chain names + genesis hashes. */\nfunction configFingerprint(chains: Record<string, ChainDefinition>): string {\n return Object.entries(chains)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([name, desc]) => `${name}:${desc.genesis ?? \"unknown\"}`)\n .join(\"|\");\n}\n\n/**\n * Create a multi-chain client with user-provided descriptors and RPC endpoints.\n *\n * Returns fully-typed APIs for each chain plus raw `PolkadotClient` access via `.raw`.\n * Connections use host routing (via `@parity/product-sdk-host`) when inside a container,\n * falling back to direct WebSocket RPC.\n *\n * Results are cached by genesis-hash fingerprint — calling with the same descriptors\n * returns the same instance.\n *\n * @example\n * ```ts\n * import { createChainClient } from \"@parity/product-sdk-chain-client\";\n * import { paseo_asset_hub } from \"./descriptors/paseo-asset-hub\";\n * import { bulletin } from \"./descriptors/bulletin\";\n *\n * const client = await createChainClient({\n * chains: { assetHub: paseo_asset_hub, bulletin },\n * rpcs: {\n * assetHub: [\"wss://sys.ibp.network/asset-hub-paseo\"],\n * bulletin: [\"wss://paseo-bulletin-rpc.polkadot.io\"],\n * },\n * });\n *\n * // Fully typed from your descriptors\n * const account = await client.assetHub.query.System.Account.getValue(addr);\n * const fee = await client.bulletin.query.TransactionStorage.ByteFee.getValue();\n *\n * // Raw client for advanced use (e.g., InkSdk for contracts)\n * import { createInkSdk } from \"@polkadot-api/sdk-ink\";\n * const inkSdk = createInkSdk(client.raw.assetHub, { atBest: true });\n *\n * // Cleanup\n * client.destroy();\n * ```\n */\nexport async function createChainClient<const TChains extends Record<string, ChainDefinition>>(\n config: ChainClientConfig<TChains>,\n): Promise<ChainClient<TChains>> {\n const fingerprint = configFingerprint(config.chains);\n\n const existing = clientInstances.get(fingerprint);\n if (existing) return existing as Promise<ChainClient<TChains>>;\n\n const promise = initChainClient(config, fingerprint).catch((err) => {\n // Clean up any clients created before the failure to avoid leaking\n // WebSocket connections that are unreachable except via destroyAll().\n const cache = getClientCache();\n for (const [key, entry] of cache) {\n if (key.startsWith(`${fingerprint}:`)) {\n try {\n entry.client.destroy();\n } catch {\n /* already destroyed */\n }\n cache.delete(key);\n }\n }\n clientInstances.delete(fingerprint);\n throw err;\n });\n clientInstances.set(fingerprint, promise);\n return promise;\n}\n\n/* @integration */\nasync function initChainClient<const TChains extends Record<string, ChainDefinition>>(\n config: ChainClientConfig<TChains>,\n fingerprint: string,\n): Promise<ChainClient<TChains>> {\n const names = Object.keys(config.chains) as (string & keyof TChains)[];\n const clientCache = getClientCache();\n\n // Create providers and clients in parallel\n const entries = await Promise.all(\n names.map(async (name) => {\n const descriptor = config.chains[name] as ChainDefinition;\n const genesis = descriptor.genesis;\n if (!genesis) {\n throw new Error(`Descriptor for chain \"${name}\" has no genesis hash.`);\n }\n const provider = await createProvider(genesis);\n const client = createClient(provider);\n\n // Populate HMR cache so getClient() and isConnected() work\n const key = cacheKey(fingerprint, genesis);\n if (!clientCache.has(key)) {\n clientCache.set(key, {\n client,\n api: new Map(),\n } satisfies ChainEntry);\n }\n\n return { name, descriptor, client, genesis };\n }),\n );\n\n // Build typed APIs and raw client map\n const apis = {} as Record<string, unknown>;\n const raw = {} as Record<string, PolkadotClient>;\n\n for (const { name, descriptor, client } of entries) {\n apis[name] = client.getTypedApi(descriptor);\n raw[name] = client;\n }\n\n return {\n ...apis,\n raw,\n destroy() {\n for (const { genesis } of entries) {\n const key = cacheKey(fingerprint, genesis);\n const entry = clientCache.get(key);\n if (entry) {\n try {\n entry.client.destroy();\n } catch {\n /* already destroyed */\n }\n clientCache.delete(key);\n }\n }\n clientInstances.delete(fingerprint);\n },\n } as ChainClient<TChains>;\n}\n\n/**\n * Destroy all chain client instances and reset internal caches.\n *\n * Tears down every connection created by {@link createChainClient}.\n */\nexport function destroyAll(): void {\n clearClientCache();\n clientInstances.clear();\n}\n\n/**\n * Get the raw `PolkadotClient` for a connected chain by its descriptor.\n *\n * The chain must have been initialized via {@link createChainClient} first.\n * Alternatively, use `client.raw.<name>` on the returned {@link ChainClient}.\n *\n * @throws If the chain has not been connected yet.\n */\nexport function getClient(descriptor: ChainDefinition): PolkadotClient {\n const genesis = descriptor.genesis;\n if (!genesis) throw new Error(\"Descriptor has no genesis hash.\");\n const entry = findEntryByGenesis(genesis);\n if (!entry?.client) {\n throw new Error(\n `Chain not connected (genesis: ${genesis}). Call createChainClient() first to establish connections.`,\n );\n }\n return entry.client;\n}\n\n/**\n * Check if a chain is currently connected.\n *\n * Synchronous — no side effects, no initialization.\n */\nexport function isConnected(descriptor: ChainDefinition): boolean {\n const genesis = descriptor.genesis;\n if (!genesis) return false;\n return findEntryByGenesis(genesis) !== undefined;\n}\n\nif (import.meta.vitest) {\n const { test, expect, beforeEach } = import.meta.vitest;\n\n const fakeDescriptor = { genesis: \"0xtest\" } as ChainDefinition;\n const fakeClient = {\n destroy: () => {},\n getTypedApi: () => ({}),\n } as unknown as PolkadotClient;\n\n function seedCache(genesis: string, client: PolkadotClient, fp = \"test\") {\n getClientCache().set(cacheKey(fp, genesis), {\n client,\n api: new Map(),\n });\n }\n\n beforeEach(() => {\n clearClientCache();\n clientInstances.clear();\n });\n\n // --- isConnected ---\n\n test(\"isConnected returns false for unknown chain\", () => {\n expect(isConnected(fakeDescriptor)).toBe(false);\n });\n\n test(\"isConnected returns true after cache is populated\", () => {\n seedCache(\"0xtest\", fakeClient);\n expect(isConnected(fakeDescriptor)).toBe(true);\n });\n\n test(\"isConnected returns false for descriptor without genesis\", () => {\n expect(isConnected({} as ChainDefinition)).toBe(false);\n });\n\n // --- getClient ---\n\n test(\"getClient returns client from cache\", () => {\n seedCache(\"0xtest\", fakeClient);\n expect(getClient(fakeDescriptor)).toBe(fakeClient);\n });\n\n test(\"getClient throws for unconnected chain\", () => {\n expect(() => getClient(fakeDescriptor)).toThrow(/Chain not connected/);\n });\n\n test(\"getClient throws for descriptor without genesis\", () => {\n expect(() => getClient({} as ChainDefinition)).toThrow(/no genesis hash/);\n });\n\n // --- destroyAll ---\n\n test(\"destroyAll calls client.destroy() and clears caches\", () => {\n let destroyed = false;\n const trackableClient = {\n destroy: () => {\n destroyed = true;\n },\n getTypedApi: () => ({}),\n } as unknown as PolkadotClient;\n seedCache(\"0xtest\", trackableClient);\n clientInstances.set(\"test\", Promise.resolve({} as ChainClient<any>));\n destroyAll();\n expect(destroyed).toBe(true);\n expect(isConnected(fakeDescriptor)).toBe(false);\n expect(clientInstances.size).toBe(0);\n });\n\n // --- createChainClient ---\n\n test(\"createChainClient returns same promise for identical config\", async () => {\n const fakeResult = {} as ChainClient<any>;\n const fp = configFingerprint({ a: fakeDescriptor });\n clientInstances.set(fp, Promise.resolve(fakeResult));\n const result = await createChainClient({\n chains: { a: fakeDescriptor },\n rpcs: { a: [] },\n });\n expect(result).toBe(fakeResult);\n });\n\n test(\"createChainClient deduplicates concurrent calls\", async () => {\n const fakeResult = {} as ChainClient<any>;\n const fp = configFingerprint({ x: fakeDescriptor });\n clientInstances.set(fp, Promise.resolve(fakeResult));\n const [a, b] = await Promise.all([\n createChainClient({ chains: { x: fakeDescriptor }, rpcs: { x: [] } }),\n createChainClient({ chains: { x: fakeDescriptor }, rpcs: { x: [] } }),\n ]);\n expect(a).toBe(b);\n });\n\n test(\"createChainClient returns different results for different configs\", async () => {\n const descA = { genesis: \"0xaaa\" } as ChainDefinition;\n const descB = { genesis: \"0xbbb\" } as ChainDefinition;\n const resultA = {} as ChainClient<any>;\n const resultB = {} as ChainClient<any>;\n clientInstances.set(configFingerprint({ a: descA }), Promise.resolve(resultA));\n clientInstances.set(configFingerprint({ b: descB }), Promise.resolve(resultB));\n const a = await createChainClient({ chains: { a: descA }, rpcs: { a: [] } });\n const b = await createChainClient({ chains: { b: descB }, rpcs: { b: [] } });\n expect(a).not.toBe(b);\n });\n\n // --- configFingerprint ---\n\n test(\"configFingerprint is stable regardless of key order\", () => {\n const d1 = { genesis: \"0x1\" } as ChainDefinition;\n const d2 = { genesis: \"0x2\" } as ChainDefinition;\n expect(configFingerprint({ a: d1, b: d2 })).toBe(configFingerprint({ b: d2, a: d1 }));\n });\n\n // --- findEntryByGenesis ---\n\n test(\"findEntryByGenesis returns undefined for missing genesis\", () => {\n expect(findEntryByGenesis(\"0xnonexistent\")).toBeUndefined();\n });\n\n // --- full lifecycle ---\n\n test(\"full lifecycle: seed, verify connected, destroy, verify disconnected\", () => {\n seedCache(\"0xtest\", fakeClient);\n expect(isConnected(fakeDescriptor)).toBe(true);\n expect(getClient(fakeDescriptor)).toBe(fakeClient);\n destroyAll();\n expect(isConnected(fakeDescriptor)).toBe(false);\n expect(() => getClient(fakeDescriptor)).toThrow(/Chain not connected/);\n });\n\n test(\"two fingerprints cached independently, destroy one leaves other intact\", () => {\n const sharedGenesis = \"0xshared\";\n const clientA = { destroy: () => {} } as PolkadotClient;\n const clientB = { destroy: () => {} } as PolkadotClient;\n const descriptorShared = { genesis: sharedGenesis } as ChainDefinition;\n\n seedCache(sharedGenesis, clientA, \"fpA\");\n seedCache(sharedGenesis, clientB, \"fpB\");\n\n expect(isConnected(descriptorShared)).toBe(true);\n\n // Destroy only fpA's entry\n const cache = getClientCache();\n const keyA = cacheKey(\"fpA\", sharedGenesis);\n cache.get(keyA)?.client.destroy();\n cache.delete(keyA);\n\n // fpB's entry still alive\n expect(isConnected(descriptorShared)).toBe(true);\n expect(getClient(descriptorShared)).toBe(clientB);\n });\n}\n","import type { ChainDefinition } from \"polkadot-api\";\nimport { BULLETIN_RPCS } from \"@parity/product-sdk-host\";\nimport { createChainClient } from \"./clients.js\";\nimport type { ChainClient } from \"./types.js\";\n\n// Type-only imports — erased at compile time, zero bundle cost.\n// These give us per-chain TypedApi types without importing runtime descriptor data.\nimport type { polkadot_asset_hub as PolkadotAssetHubDef } from \"@parity/product-sdk-descriptors/polkadot-asset-hub\";\nimport type { kusama_asset_hub as KusamaAssetHubDef } from \"@parity/product-sdk-descriptors/kusama-asset-hub\";\nimport type { paseo_asset_hub as PaseoAssetHubDef } from \"@parity/product-sdk-descriptors/paseo-asset-hub\";\nimport type { bulletin as BulletinDef } from \"@parity/product-sdk-descriptors/bulletin\";\nimport type { individuality as IndividualityDef } from \"@parity/product-sdk-descriptors/individuality\";\n\n/** Known network environment with built-in descriptors and RPC endpoints. */\nexport type Environment = \"polkadot\" | \"kusama\" | \"paseo\";\n\n/** Environments where all chains (asset hub, bulletin, individuality) are live. */\nconst AVAILABLE_ENVIRONMENTS: Set<Environment> = new Set([\"paseo\"]);\n\nconst rpcs = {\n polkadot: {\n assetHub: [\n \"wss://polkadot-asset-hub-rpc.polkadot.io\",\n \"wss://sys.ibp.network/asset-hub-polkadot\",\n ],\n bulletin: [...BULLETIN_RPCS.polkadot],\n individuality: [] as string[],\n },\n kusama: {\n assetHub: [\n \"wss://kusama-asset-hub-rpc.polkadot.io\",\n \"wss://sys.ibp.network/asset-hub-kusama\",\n ],\n bulletin: [...BULLETIN_RPCS.kusama],\n individuality: [] as string[],\n },\n paseo: {\n assetHub: [\n \"wss://asset-hub-paseo-rpc.n.dwellir.com\",\n \"wss://sys.ibp.network/asset-hub-paseo\",\n ],\n bulletin: [...BULLETIN_RPCS.paseo],\n individuality: [\"wss://paseo-people-next-rpc.polkadot.io\"],\n },\n} as const;\n\n/**\n * Lazy-load descriptors for a specific environment.\n * Only imports the chains needed — avoids bundling all 5 chains when\n * a consumer only uses one environment.\n */\nasync function loadDescriptors(env: Environment) {\n const assetHubImport = {\n polkadot: () => import(\"@parity/product-sdk-descriptors/polkadot-asset-hub\"),\n kusama: () => import(\"@parity/product-sdk-descriptors/kusama-asset-hub\"),\n paseo: () => import(\"@parity/product-sdk-descriptors/paseo-asset-hub\"),\n }[env]();\n\n const [ahMod, { bulletin }, { individuality }] = await Promise.all([\n assetHubImport,\n import(\"@parity/product-sdk-descriptors/bulletin\"),\n import(\"@parity/product-sdk-descriptors/individuality\"),\n ]);\n\n // Extract the asset hub descriptor (the named export varies per environment)\n const assetHub =\n \"polkadot_asset_hub\" in ahMod\n ? ahMod.polkadot_asset_hub\n : \"kusama_asset_hub\" in ahMod\n ? ahMod.kusama_asset_hub\n : (ahMod as typeof import(\"@parity/product-sdk-descriptors/paseo-asset-hub\"))\n .paseo_asset_hub;\n\n return { assetHub, bulletin, individuality };\n}\n\n/** Maps each environment to its asset hub descriptor type. */\ntype AssetHubDescriptors = {\n polkadot: typeof PolkadotAssetHubDef;\n kusama: typeof KusamaAssetHubDef;\n paseo: typeof PaseoAssetHubDef;\n};\n\n/** The chain shape returned by {@link getChainAPI} for a given environment. */\nexport type PresetChains<E extends Environment> = {\n assetHub: AssetHubDescriptors[E];\n bulletin: typeof BulletinDef;\n individuality: typeof IndividualityDef;\n};\n\n/**\n * Get a chain client for a known environment with built-in descriptors and RPCs.\n *\n * This is the **zero-config** path — no need to import descriptors or specify\n * endpoints. For custom chains or BYOD descriptors, use\n * {@link createChainClient} instead.\n *\n * Returns the same {@link ChainClient} type as `createChainClient`, with\n * `assetHub`, `bulletin`, and `individuality` chain keys.\n *\n * @example\n * ```ts\n * import { getChainAPI } from \"@parity/product-sdk-chain-client\";\n *\n * const client = await getChainAPI(\"paseo\");\n *\n * // Fully typed — no descriptor imports needed\n * const account = await client.assetHub.query.System.Account.getValue(addr);\n * const fee = await client.bulletin.query.TransactionStorage.ByteFee.getValue();\n *\n * // Raw client for advanced use (e.g., InkSdk for contracts)\n * import { createInkSdk } from \"@polkadot-api/sdk-ink\";\n * const inkSdk = createInkSdk(client.raw.assetHub, { atBest: true });\n *\n * client.destroy();\n * ```\n */\nexport async function getChainAPI<E extends Environment>(\n env: E,\n): Promise<ChainClient<PresetChains<E>>> {\n if (!AVAILABLE_ENVIRONMENTS.has(env)) {\n throw new Error(`Chain API for \"${env}\" is not yet available`);\n }\n\n const descriptors = await loadDescriptors(env);\n const envRpcs = rpcs[env];\n\n return createChainClient({\n chains: {\n assetHub: descriptors.assetHub,\n bulletin: descriptors.bulletin,\n individuality: descriptors.individuality,\n },\n rpcs: {\n assetHub: [...envRpcs.assetHub],\n bulletin: [...envRpcs.bulletin],\n individuality: [...envRpcs.individuality],\n },\n }) as Promise<ChainClient<PresetChains<E>>>;\n}\n\nif (import.meta.vitest) {\n const { test, expect, beforeEach } = import.meta.vitest;\n const { destroyAll } = await import(\"./clients.js\");\n\n // Test-only genesis hashes for assertion — not used in production code.\n const GENESIS = {\n polkadot_asset_hub: \"0x68d56f15f85d3136970ec16946040bc1752654e906147f7e43e9d539d7c3de2f\",\n kusama_asset_hub: \"0x48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a\",\n paseo_asset_hub: \"0xd6eec26135305a8ad257a20d003357284c8aa03d0bdb2b357ab0a22371e11ef2\",\n bulletin: \"0x744960c32e3a3df5440e1ecd4d34096f1ce2230d7016a5ada8a765d5a622b4ea\",\n individuality: \"0xd01475fde5d0592989b7715ae1d2e89fdb4f8c7688c09c850d75e1d4bdb47d64\",\n } as const;\n\n beforeEach(() => {\n destroyAll();\n });\n\n // --- GENESIS constants ---\n\n test(\"genesis constants are valid hex hashes\", () => {\n for (const hash of Object.values(GENESIS)) {\n expect(hash).toMatch(/^0x[a-f0-9]{64}$/);\n }\n });\n\n // --- RPC config ---\n\n test(\"rpcs defined for all environments\", () => {\n for (const env of [\"polkadot\", \"kusama\", \"paseo\"] as const) {\n const envRpcs = rpcs[env];\n expect(envRpcs.assetHub.length).toBeGreaterThan(0);\n }\n });\n\n test(\"paseo has RPCs for all chains\", () => {\n const envRpcs = rpcs.paseo;\n expect(envRpcs.bulletin.length).toBeGreaterThan(0);\n expect(envRpcs.individuality.length).toBeGreaterThan(0);\n });\n\n // --- getChainAPI ---\n\n test(\"polkadot and kusama throw as not yet available\", async () => {\n await expect(getChainAPI(\"polkadot\")).rejects.toThrow(\"not yet available\");\n await expect(getChainAPI(\"kusama\")).rejects.toThrow(\"not yet available\");\n });\n\n // --- loadDescriptors ---\n\n test(\"loadDescriptors returns descriptors with genesis hashes for paseo\", async () => {\n const descriptors = await loadDescriptors(\"paseo\");\n expect(descriptors).toBeDefined();\n expect(descriptors.assetHub).toBeDefined();\n expect(descriptors.bulletin).toBeDefined();\n expect(descriptors.individuality).toBeDefined();\n expect(descriptors.assetHub.genesis).toBe(GENESIS.paseo_asset_hub);\n expect(descriptors.bulletin.genesis).toBe(GENESIS.bulletin);\n expect(descriptors.individuality.genesis).toBe(GENESIS.individuality);\n });\n\n test(\"loadDescriptors returns correct asset hub per environment\", async () => {\n const polkadot = await loadDescriptors(\"polkadot\");\n const kusama = await loadDescriptors(\"kusama\");\n const paseo = await loadDescriptors(\"paseo\");\n expect(polkadot.assetHub.genesis).toBe(GENESIS.polkadot_asset_hub);\n expect(kusama.assetHub.genesis).toBe(GENESIS.kusama_asset_hub);\n expect(paseo.assetHub.genesis).toBe(GENESIS.paseo_asset_hub);\n // bulletin and individuality are the same across environments\n expect(polkadot.bulletin.genesis).toBe(paseo.bulletin.genesis);\n expect(polkadot.individuality.genesis).toBe(paseo.individuality.genesis);\n });\n\n // --- AVAILABLE_ENVIRONMENTS ---\n\n test(\"only paseo is currently available\", () => {\n expect(AVAILABLE_ENVIRONMENTS.has(\"paseo\")).toBe(true);\n expect(AVAILABLE_ENVIRONMENTS.has(\"polkadot\")).toBe(false);\n expect(AVAILABLE_ENVIRONMENTS.has(\"kusama\")).toBe(false);\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parity/product-sdk-chain-client",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Multi-chain Polkadot API client with typed access to Asset Hub, Bulletin, and other chains",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -18,10 +18,10 @@
18
18
  "src"
19
19
  ],
20
20
  "dependencies": {
21
- "polkadot-api": "^1.9.0",
22
- "@parity/product-sdk-descriptors": "0.1.0",
23
- "@parity/product-sdk-logger": "0.1.0",
24
- "@parity/product-sdk-host": "0.1.0"
21
+ "polkadot-api": "^2.1.2",
22
+ "@parity/product-sdk-descriptors": "0.2.0",
23
+ "@parity/product-sdk-logger": "0.1.1",
24
+ "@parity/product-sdk-host": "0.2.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "tsup": "^8.4.0",
package/src/index.ts CHANGED
@@ -1,3 +1,15 @@
1
+ /**
2
+ * @parity/product-sdk-chain-client — Typed, multi-chain Polkadot API client.
3
+ *
4
+ * Pick the entry point that fits how much you want to wire up yourself:
5
+ * `getChainAPI` is the zero-config path with built-in descriptors and RPC endpoints
6
+ * (Paseo is live today; Polkadot and Kusama are reserved but not yet enabled), and
7
+ * `createChainClient` is the bring-your-own-descriptors path for custom or
8
+ * pre-release chains.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+
1
13
  // Core BYOD API — zero descriptor overhead
2
14
  export { createChainClient, destroyAll, getClient, isConnected } from "./clients.js";
3
15
 
package/src/providers.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { getHostProvider } from "@parity/product-sdk-host";
2
- import type { JsonRpcProvider } from "polkadot-api/ws-provider/web";
2
+ import type { JsonRpcProvider } from "polkadot-api";
3
3
 
4
4
  /**
5
5
  * Create a PAPI-compatible JSON-RPC provider for a chain.