polkadot-api 1.16.4 → 1.17.1

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/bin/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { getCli, ink, update, remove, generate, add } from '@polkadot-api/cli';
3
3
 
4
- var version = "1.16.4";
4
+ var version = "1.17.1";
5
5
 
6
6
  getCli({
7
7
  add,
@@ -217,14 +217,17 @@ function createClient(provider, { getMetadata, setMetadata } = {}) {
217
217
  let runtimeToken;
218
218
  const compatibilityToken = /* @__PURE__ */ new WeakMap();
219
219
  const getChainToken = (chainDefinition) => {
220
- const result = compatibilityToken.get(chainDefinition) || createCompatibilityToken(chainDefinition, chainHead);
221
- compatibilityToken.set(chainDefinition, result);
222
- return result;
220
+ const result2 = compatibilityToken.get(chainDefinition) || createCompatibilityToken(chainDefinition, chainHead);
221
+ compatibilityToken.set(chainDefinition, result2);
222
+ return result2;
223
223
  };
224
224
  const getRuntimeToken = () => runtimeToken ?? (runtimeToken = createRuntimeToken(chainHead));
225
225
  const { broadcastTx$ } = client;
226
- return {
226
+ const getMetadata$ = (at) => chainHead.getRuntimeContext$(at).pipe(map((ctx) => ctx.metadataRaw));
227
+ const result = {
227
228
  getChainSpecData,
229
+ getMetadata$,
230
+ getMetadata: (atBlock, signal) => firstValueFromWithSignal(getMetadata$(atBlock), signal),
228
231
  blocks$: chainHead.newBlocks$,
229
232
  hodlBlock: (block) => chainHead.holdBlock(block, true),
230
233
  finalizedBlock$: chainHead.finalized$,
@@ -262,6 +265,8 @@ function createClient(provider, { getMetadata, setMetadata } = {}) {
262
265
  },
263
266
  _request
264
267
  };
268
+ result.___INTERNAL_DO_NOT_USE = chainHead;
269
+ return result;
265
270
  }
266
271
 
267
272
  export { createClient };
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","sources":["../../src/client.ts"],"sourcesContent":["import { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport {\n enumValueEntryPointNode,\n runtimeCallEntryPoint,\n singleValueEntryPoint,\n storageEntryPoint,\n voidEntryPointNode,\n} from \"@polkadot-api/metadata-compatibility\"\nimport {\n ChainHead$,\n RuntimeContext,\n getObservableClient,\n withArchive,\n} from \"@polkadot-api/observable-client\"\nimport { Binary, HexString } from \"@polkadot-api/substrate-bindings\"\nimport {\n SubstrateClient,\n createClient as createRawClient,\n} from \"@polkadot-api/substrate-client\"\nimport {\n Observable,\n catchError,\n defer,\n firstValueFrom,\n from,\n map,\n shareReplay,\n} from \"rxjs\"\nimport {\n CompatibilityToken,\n OpType,\n RuntimeToken,\n compatibilityHelper,\n createCompatibilityToken,\n createRuntimeToken,\n getCompatibilityApi,\n} from \"./compatibility\"\nimport { createConstantEntry } from \"./constants\"\nimport { ChainDefinition } from \"./descriptors\"\nimport { createEventEntry } from \"./event\"\nimport { createRuntimeCallEntry } from \"./runtime-call\"\nimport { createStorageEntry } from \"./storage\"\nimport { createTxEntry, submit, submit$ } from \"./tx\"\nimport type { AnyApi, PolkadotClient } from \"./types\"\nimport { createWatchEntries } from \"./watch-entries\"\nimport { createViewFnEntry } from \"./viewFns\"\nimport { firstValueFromWithSignal } from \"./utils\"\n\nconst HEX_REGEX = /^(?:0x)?((?:[0-9a-fA-F][0-9a-fA-F])+)$/\n\nconst createApi = <Unsafe extends true | false, D>(\n compatibilityToken: Promise<CompatibilityToken | RuntimeToken>,\n chainHead: ChainHead$,\n broadcast$: (tx: string) => Observable<never>,\n): AnyApi<Unsafe, D> => {\n const target = {}\n const createProxy = (propCall: (prop: string) => unknown) =>\n new Proxy(target, {\n get(_, prop) {\n return propCall(prop as string)\n },\n })\n const createProxyPath = <T>(pathCall: (a: string, b: string) => T) => {\n const cache: Record<string, Record<string, T>> = {}\n return createProxy((a) => {\n if (!cache[a]) cache[a] = {}\n return createProxy((b) => {\n if (!cache[a][b]) cache[a][b] = pathCall(a, b)\n return cache[a][b]\n })\n }) as Record<string, Record<string, T>>\n }\n\n const getPallet = (ctx: RuntimeContext, name: string) =>\n ctx.lookup.metadata.pallets.find((p) => p.name === name)\n\n const getWatchEntries = createWatchEntries(\n chainHead.pinnedBlocks$,\n chainHead.storage$,\n chainHead.withRuntime,\n )\n const query = createProxyPath((pallet, name) =>\n createStorageEntry(\n pallet,\n name,\n chainHead,\n getWatchEntries,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Storage, pallet, name),\n // TODO this is way sub-optimal. Needs some rethought - maybe a builder for entry points?.\n (ctx) => {\n const item = getPallet(ctx, pallet)?.storage?.items.find(\n (s) => s.name === name,\n )\n return item == null ? null : storageEntryPoint(item)\n },\n ),\n ),\n )\n\n const getEnumEntry = (\n ctx: RuntimeContext,\n side: \"args\" | \"values\",\n id: number | undefined,\n name: string,\n ) => {\n if (id == null) return null\n const entry = ctx.lookup(id)\n if (entry.type !== \"enum\") throw new Error(\"Expected enum\")\n\n if (entry.value[name] == null) return null\n const node = enumValueEntryPointNode(entry.value[name])\n return {\n args: side === \"args\" ? node : voidEntryPointNode,\n values: side === \"args\" ? voidEntryPointNode : node,\n }\n }\n const tx = createProxyPath((pallet, name) =>\n createTxEntry(\n pallet,\n name,\n chainHead,\n broadcast$,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Tx, pallet, name),\n (ctx) =>\n getEnumEntry(ctx, \"args\", getPallet(ctx, pallet)?.calls?.type, name),\n ),\n true,\n ),\n )\n\n const event = createProxyPath((pallet, name) =>\n createEventEntry(\n pallet,\n name,\n chainHead,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Event, pallet, name),\n (ctx) =>\n getEnumEntry(\n ctx,\n \"values\",\n getPallet(ctx, pallet)?.events?.type,\n name,\n ),\n ),\n ),\n )\n\n const constants = createProxyPath((pallet, name) =>\n createConstantEntry(\n pallet,\n name,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Const, pallet, name),\n (ctx) => {\n const item = getPallet(ctx, pallet)?.constants.find(\n (c) => c.name === name,\n )?.type\n return item == null ? null : singleValueEntryPoint(item)\n },\n ),\n ),\n )\n\n const apis = createProxyPath((api, method) =>\n createRuntimeCallEntry(\n api,\n method,\n chainHead,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Api, api, method),\n (ctx) =>\n runtimeCallEntryPoint(\n ctx.lookup.metadata.apis\n .find((a) => a.name === api)!\n .methods.find((m) => m.name === method)!,\n ),\n ),\n ),\n )\n const view = createProxyPath((pallet, entry) =>\n createViewFnEntry(\n pallet,\n entry,\n chainHead,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.ViewFns, pallet, entry),\n (ctx) =>\n runtimeCallEntryPoint(\n ctx.lookup.metadata.pallets\n .find((a) => a.name === pallet)!\n .viewFns.find((m) => m.name === entry)!,\n ),\n ),\n ),\n )\n\n const _callDataTx = (\n callData: Binary,\n token: CompatibilityToken | RuntimeToken,\n ) => {\n const { lookup, dynamicBuilder } = getCompatibilityApi(token).runtime()\n try {\n const decoded = dynamicBuilder\n .buildDefinition(lookup.call!)\n .dec(callData.asBytes())\n const pallet = decoded.type\n const call = decoded.value.type\n const args = decoded.value.value\n\n return createTxEntry(\n pallet,\n call,\n chainHead,\n broadcast$,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Tx, pallet, call),\n (ctx) =>\n getEnumEntry(\n ctx,\n \"args\",\n getPallet(ctx, pallet)?.calls?.type,\n call,\n ),\n ),\n false,\n )(args)\n } catch {\n throw new Error(\"createTx: invalid call data\")\n }\n }\n\n return {\n query,\n txFromCallData: (\n callData: Binary,\n token?: CompatibilityToken | RuntimeToken,\n ) =>\n token\n ? _callDataTx(callData, token)\n : compatibilityToken.then((t) => _callDataTx(callData, t)),\n tx,\n event,\n apis,\n constants,\n view,\n } as any\n}\n\nexport type CreateClientOptions = Partial<{\n getMetadata: (codeHash: HexString) => Promise<Uint8Array | null>\n setMetadata: (codeHash: HexString, metadata: Uint8Array) => void\n}>\n\n/**\n * This is the top-level export for `polkadot-api`.\n *\n * @param provider A `JsonRpcProvider` compliant with the [JSON-RPC\n * spec](https://paritytech.github.io/json-rpc-interface-spec/),\n * which must support the `chainHead`, `transaction` and\n * `chainSpec` groups.\n * @param options - *(Optional)* An object that allows customization of\n * metadata handling.\n * You can supply functions to retrieve and/or persist the\n * metadata associated with runtime `codeHash` values:\n *\n * - `getMetadata`: A function that, given a `codeHash` (the\n * `:code:` hash),\n * returns a `Promise` resolving to a `Uint8Array`\n * representing the metadata,\n * or `null` if unavailable.\n * - `setMetadata`: A function that accepts a `codeHash` and\n * its associated `Uint8Array` metadata,\n * allowing you to persist the metadata (e.g., in a cache or\n * local store).\n * @example\n *\n * import { getMetadata } from \"@polkadot-api/descriptors\"\n * import { createClient } from \"polkadot-api\"\n * import { getSmProvider } from \"polkadot-api/sm-provider\"\n * import { chainSpec } from \"polkadot-api/chains/polkadot\"\n * import { start } from \"polkadot-api/smoldot\"\n *\n * const smoldot = start()\n * const chain = await smoldot.addChain({ chainSpec })\n *\n * // Connect to the polkadot relay chain.\n * const client = createClient(getSmProvider(chain), { getMetadata })\n *\n */\nexport function createClient(\n provider: JsonRpcProvider,\n { getMetadata, setMetadata }: CreateClientOptions = {},\n): PolkadotClient {\n const rawClient: SubstrateClient = createRawClient(provider)\n const client = getObservableClient(rawClient, {\n getMetadata: getMetadata\n ? (codeHash: string) => from(getMetadata(codeHash))\n : undefined,\n setMetadata,\n })\n const { getChainSpecData } = rawClient\n\n const { genesis$, ..._chainHead } = client.chainHead$()\n const archive = client.archive(_chainHead.getRuntime$)\n const chainHead: ChainHead$ = {\n ..._chainHead,\n genesis$: defer(getChainSpecData).pipe(\n map(({ genesisHash }) => genesisHash),\n catchError(() => genesis$),\n shareReplay(1),\n ),\n storage$: withArchive(_chainHead.storage$, archive.storage$),\n body$: withArchive(_chainHead.body$, archive.body$),\n call$: withArchive(_chainHead.call$, archive.call$),\n header$: withArchive(_chainHead.header$, archive.header$),\n eventsAt$: withArchive(_chainHead.eventsAt$, archive.eventsAt$),\n storageQueries$: withArchive(\n _chainHead.storageQueries$,\n archive.storageQueries$,\n ),\n getRuntimeContext$: withArchive(\n _chainHead.getRuntimeContext$,\n archive.getRuntimeContext$,\n ),\n }\n\n const _request: <Reply = any, Params extends Array<any> = any[]>(\n method: string,\n params: Params,\n ) => Promise<Reply> = rawClient.request\n\n let runtimeToken: Promise<RuntimeToken>\n const compatibilityToken = new WeakMap<\n ChainDefinition,\n Promise<CompatibilityToken<any>>\n >()\n const getChainToken = (chainDefinition: ChainDefinition) => {\n const result =\n compatibilityToken.get(chainDefinition) ||\n createCompatibilityToken(chainDefinition, chainHead)\n compatibilityToken.set(chainDefinition, result)\n return result\n }\n const getRuntimeToken = <D>(): Promise<RuntimeToken<D>> =>\n (runtimeToken ??= createRuntimeToken(chainHead))\n const { broadcastTx$ } = client\n\n return {\n getChainSpecData,\n\n blocks$: chainHead.newBlocks$,\n hodlBlock: (block: HexString) => chainHead.holdBlock(block, true),\n\n finalizedBlock$: chainHead.finalized$,\n getFinalizedBlock: () => firstValueFrom(chainHead.finalized$),\n\n bestBlocks$: chainHead.bestBlocks$,\n getBestBlocks: () => firstValueFrom(chainHead.bestBlocks$),\n\n watchBlockBody: chainHead.body$,\n getBlockBody: (hash: string) => firstValueFrom(chainHead.body$(hash)),\n\n getBlockHeader: (hash?: string) =>\n firstValueFrom(chainHead.header$(hash ?? null)),\n\n submit: (...args) => submit(chainHead, broadcastTx$, ...args),\n submitAndWatch: (tx) => submit$(chainHead, broadcastTx$, tx),\n\n getTypedApi: <D extends ChainDefinition>(chainDefinition: D) => {\n const token = getChainToken(chainDefinition)\n return Object.assign(\n createApi<false, D>(token, chainHead, broadcastTx$),\n { compatibilityToken: token },\n )\n },\n\n getUnsafeApi: <D>() => {\n const token = getRuntimeToken()\n return Object.assign(createApi<true, D>(token, chainHead, broadcastTx$), {\n runtimeToken: token,\n })\n },\n\n rawQuery: (key, { at, signal } = {}) =>\n firstValueFromWithSignal(\n chainHead.storage$(at ?? null, \"value\", () => {\n const hex = key.match(HEX_REGEX)?.[1]\n return hex ? `0x${hex}` : Binary.fromText(key).asHex()\n }),\n signal,\n ),\n\n destroy: () => {\n chainHead.unfollow()\n client.destroy()\n },\n\n _request,\n }\n}\n"],"names":["createRawClient"],"mappings":"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"}
1
+ {"version":3,"file":"client.mjs","sources":["../../src/client.ts"],"sourcesContent":["import { JsonRpcProvider } from \"@polkadot-api/json-rpc-provider\"\nimport {\n enumValueEntryPointNode,\n runtimeCallEntryPoint,\n singleValueEntryPoint,\n storageEntryPoint,\n voidEntryPointNode,\n} from \"@polkadot-api/metadata-compatibility\"\nimport {\n ChainHead$,\n RuntimeContext,\n getObservableClient,\n withArchive,\n} from \"@polkadot-api/observable-client\"\nimport { Binary, HexString } from \"@polkadot-api/substrate-bindings\"\nimport {\n SubstrateClient,\n createClient as createRawClient,\n} from \"@polkadot-api/substrate-client\"\nimport {\n Observable,\n catchError,\n defer,\n firstValueFrom,\n from,\n map,\n shareReplay,\n} from \"rxjs\"\nimport {\n CompatibilityToken,\n OpType,\n RuntimeToken,\n compatibilityHelper,\n createCompatibilityToken,\n createRuntimeToken,\n getCompatibilityApi,\n} from \"./compatibility\"\nimport { createConstantEntry } from \"./constants\"\nimport { ChainDefinition } from \"./descriptors\"\nimport { createEventEntry } from \"./event\"\nimport { createRuntimeCallEntry } from \"./runtime-call\"\nimport { createStorageEntry } from \"./storage\"\nimport { createTxEntry, submit, submit$ } from \"./tx\"\nimport type { AnyApi, PolkadotClient } from \"./types\"\nimport { createWatchEntries } from \"./watch-entries\"\nimport { createViewFnEntry } from \"./viewFns\"\nimport { firstValueFromWithSignal } from \"./utils\"\n\nconst HEX_REGEX = /^(?:0x)?((?:[0-9a-fA-F][0-9a-fA-F])+)$/\n\nconst createApi = <Unsafe extends true | false, D>(\n compatibilityToken: Promise<CompatibilityToken | RuntimeToken>,\n chainHead: ChainHead$,\n broadcast$: (tx: string) => Observable<never>,\n): AnyApi<Unsafe, D> => {\n const target = {}\n const createProxy = (propCall: (prop: string) => unknown) =>\n new Proxy(target, {\n get(_, prop) {\n return propCall(prop as string)\n },\n })\n const createProxyPath = <T>(pathCall: (a: string, b: string) => T) => {\n const cache: Record<string, Record<string, T>> = {}\n return createProxy((a) => {\n if (!cache[a]) cache[a] = {}\n return createProxy((b) => {\n if (!cache[a][b]) cache[a][b] = pathCall(a, b)\n return cache[a][b]\n })\n }) as Record<string, Record<string, T>>\n }\n\n const getPallet = (ctx: RuntimeContext, name: string) =>\n ctx.lookup.metadata.pallets.find((p) => p.name === name)\n\n const getWatchEntries = createWatchEntries(\n chainHead.pinnedBlocks$,\n chainHead.storage$,\n chainHead.withRuntime,\n )\n const query = createProxyPath((pallet, name) =>\n createStorageEntry(\n pallet,\n name,\n chainHead,\n getWatchEntries,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Storage, pallet, name),\n // TODO this is way sub-optimal. Needs some rethought - maybe a builder for entry points?.\n (ctx) => {\n const item = getPallet(ctx, pallet)?.storage?.items.find(\n (s) => s.name === name,\n )\n return item == null ? null : storageEntryPoint(item)\n },\n ),\n ),\n )\n\n const getEnumEntry = (\n ctx: RuntimeContext,\n side: \"args\" | \"values\",\n id: number | undefined,\n name: string,\n ) => {\n if (id == null) return null\n const entry = ctx.lookup(id)\n if (entry.type !== \"enum\") throw new Error(\"Expected enum\")\n\n if (entry.value[name] == null) return null\n const node = enumValueEntryPointNode(entry.value[name])\n return {\n args: side === \"args\" ? node : voidEntryPointNode,\n values: side === \"args\" ? voidEntryPointNode : node,\n }\n }\n const tx = createProxyPath((pallet, name) =>\n createTxEntry(\n pallet,\n name,\n chainHead,\n broadcast$,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Tx, pallet, name),\n (ctx) =>\n getEnumEntry(ctx, \"args\", getPallet(ctx, pallet)?.calls?.type, name),\n ),\n true,\n ),\n )\n\n const event = createProxyPath((pallet, name) =>\n createEventEntry(\n pallet,\n name,\n chainHead,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Event, pallet, name),\n (ctx) =>\n getEnumEntry(\n ctx,\n \"values\",\n getPallet(ctx, pallet)?.events?.type,\n name,\n ),\n ),\n ),\n )\n\n const constants = createProxyPath((pallet, name) =>\n createConstantEntry(\n pallet,\n name,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Const, pallet, name),\n (ctx) => {\n const item = getPallet(ctx, pallet)?.constants.find(\n (c) => c.name === name,\n )?.type\n return item == null ? null : singleValueEntryPoint(item)\n },\n ),\n ),\n )\n\n const apis = createProxyPath((api, method) =>\n createRuntimeCallEntry(\n api,\n method,\n chainHead,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Api, api, method),\n (ctx) =>\n runtimeCallEntryPoint(\n ctx.lookup.metadata.apis\n .find((a) => a.name === api)!\n .methods.find((m) => m.name === method)!,\n ),\n ),\n ),\n )\n const view = createProxyPath((pallet, entry) =>\n createViewFnEntry(\n pallet,\n entry,\n chainHead,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.ViewFns, pallet, entry),\n (ctx) =>\n runtimeCallEntryPoint(\n ctx.lookup.metadata.pallets\n .find((a) => a.name === pallet)!\n .viewFns.find((m) => m.name === entry)!,\n ),\n ),\n ),\n )\n\n const _callDataTx = (\n callData: Binary,\n token: CompatibilityToken | RuntimeToken,\n ) => {\n const { lookup, dynamicBuilder } = getCompatibilityApi(token).runtime()\n try {\n const decoded = dynamicBuilder\n .buildDefinition(lookup.call!)\n .dec(callData.asBytes())\n const pallet = decoded.type\n const call = decoded.value.type\n const args = decoded.value.value\n\n return createTxEntry(\n pallet,\n call,\n chainHead,\n broadcast$,\n compatibilityHelper(\n compatibilityToken,\n (r) => r.getEntryPoint(OpType.Tx, pallet, call),\n (ctx) =>\n getEnumEntry(\n ctx,\n \"args\",\n getPallet(ctx, pallet)?.calls?.type,\n call,\n ),\n ),\n false,\n )(args)\n } catch {\n throw new Error(\"createTx: invalid call data\")\n }\n }\n\n return {\n query,\n txFromCallData: (\n callData: Binary,\n token?: CompatibilityToken | RuntimeToken,\n ) =>\n token\n ? _callDataTx(callData, token)\n : compatibilityToken.then((t) => _callDataTx(callData, t)),\n tx,\n event,\n apis,\n constants,\n view,\n } as any\n}\n\nexport type CreateClientOptions = Partial<{\n getMetadata: (codeHash: HexString) => Promise<Uint8Array | null>\n setMetadata: (codeHash: HexString, metadata: Uint8Array) => void\n}>\n\n/**\n * This is the top-level export for `polkadot-api`.\n *\n * @param provider A `JsonRpcProvider` compliant with the [JSON-RPC\n * spec](https://paritytech.github.io/json-rpc-interface-spec/),\n * which must support the `chainHead`, `transaction` and\n * `chainSpec` groups.\n * @param options - *(Optional)* An object that allows customization of\n * metadata handling.\n * You can supply functions to retrieve and/or persist the\n * metadata associated with runtime `codeHash` values:\n *\n * - `getMetadata`: A function that, given a `codeHash` (the\n * `:code:` hash),\n * returns a `Promise` resolving to a `Uint8Array`\n * representing the metadata,\n * or `null` if unavailable.\n * - `setMetadata`: A function that accepts a `codeHash` and\n * its associated `Uint8Array` metadata,\n * allowing you to persist the metadata (e.g., in a cache or\n * local store).\n * @example\n *\n * import { getMetadata } from \"@polkadot-api/descriptors\"\n * import { createClient } from \"polkadot-api\"\n * import { getSmProvider } from \"polkadot-api/sm-provider\"\n * import { chainSpec } from \"polkadot-api/chains/polkadot\"\n * import { start } from \"polkadot-api/smoldot\"\n *\n * const smoldot = start()\n * const chain = await smoldot.addChain({ chainSpec })\n *\n * // Connect to the polkadot relay chain.\n * const client = createClient(getSmProvider(chain), { getMetadata })\n *\n */\nexport function createClient(\n provider: JsonRpcProvider,\n { getMetadata, setMetadata }: CreateClientOptions = {},\n): PolkadotClient {\n const rawClient: SubstrateClient = createRawClient(provider)\n const client = getObservableClient(rawClient, {\n getMetadata: getMetadata\n ? (codeHash: string) => from(getMetadata(codeHash))\n : undefined,\n setMetadata,\n })\n const { getChainSpecData } = rawClient\n\n const { genesis$, ..._chainHead } = client.chainHead$()\n const archive = client.archive(_chainHead.getRuntime$)\n const chainHead: ChainHead$ = {\n ..._chainHead,\n genesis$: defer(getChainSpecData).pipe(\n map(({ genesisHash }) => genesisHash),\n catchError(() => genesis$),\n shareReplay(1),\n ),\n storage$: withArchive(_chainHead.storage$, archive.storage$),\n body$: withArchive(_chainHead.body$, archive.body$),\n call$: withArchive(_chainHead.call$, archive.call$),\n header$: withArchive(_chainHead.header$, archive.header$),\n eventsAt$: withArchive(_chainHead.eventsAt$, archive.eventsAt$),\n storageQueries$: withArchive(\n _chainHead.storageQueries$,\n archive.storageQueries$,\n ),\n getRuntimeContext$: withArchive(\n _chainHead.getRuntimeContext$,\n archive.getRuntimeContext$,\n ),\n }\n\n const _request: <Reply = any, Params extends Array<any> = any[]>(\n method: string,\n params: Params,\n ) => Promise<Reply> = rawClient.request\n\n let runtimeToken: Promise<RuntimeToken>\n const compatibilityToken = new WeakMap<\n ChainDefinition,\n Promise<CompatibilityToken<any>>\n >()\n const getChainToken = (chainDefinition: ChainDefinition) => {\n const result =\n compatibilityToken.get(chainDefinition) ||\n createCompatibilityToken(chainDefinition, chainHead)\n compatibilityToken.set(chainDefinition, result)\n return result\n }\n const getRuntimeToken = <D>(): Promise<RuntimeToken<D>> =>\n (runtimeToken ??= createRuntimeToken(chainHead))\n const { broadcastTx$ } = client\n\n const getMetadata$ = (at: HexString) =>\n chainHead.getRuntimeContext$(at).pipe(map((ctx) => ctx.metadataRaw))\n\n const result: PolkadotClient = {\n getChainSpecData,\n\n getMetadata$,\n getMetadata: (atBlock: HexString, signal?: AbortSignal) =>\n firstValueFromWithSignal(getMetadata$(atBlock), signal),\n\n blocks$: chainHead.newBlocks$,\n hodlBlock: (block: HexString) => chainHead.holdBlock(block, true),\n\n finalizedBlock$: chainHead.finalized$,\n getFinalizedBlock: () => firstValueFrom(chainHead.finalized$),\n\n bestBlocks$: chainHead.bestBlocks$,\n getBestBlocks: () => firstValueFrom(chainHead.bestBlocks$),\n\n watchBlockBody: chainHead.body$,\n getBlockBody: (hash: string) => firstValueFrom(chainHead.body$(hash)),\n\n getBlockHeader: (hash?: string) =>\n firstValueFrom(chainHead.header$(hash ?? null)),\n\n submit: (...args) => submit(chainHead, broadcastTx$, ...args),\n submitAndWatch: (tx) => submit$(chainHead, broadcastTx$, tx),\n\n getTypedApi: <D extends ChainDefinition>(chainDefinition: D) => {\n const token = getChainToken(chainDefinition)\n return Object.assign(\n createApi<false, D>(token, chainHead, broadcastTx$),\n { compatibilityToken: token },\n )\n },\n\n getUnsafeApi: <D>() => {\n const token = getRuntimeToken()\n return Object.assign(createApi<true, D>(token, chainHead, broadcastTx$), {\n runtimeToken: token,\n })\n },\n\n rawQuery: (key, { at, signal } = {}) =>\n firstValueFromWithSignal(\n chainHead.storage$(at ?? null, \"value\", () => {\n const hex = key.match(HEX_REGEX)?.[1]\n return hex ? `0x${hex}` : Binary.fromText(key).asHex()\n }),\n signal,\n ),\n\n destroy: () => {\n chainHead.unfollow()\n client.destroy()\n },\n\n _request,\n }\n\n ;(result as any).___INTERNAL_DO_NOT_USE = chainHead\n\n return result\n}\n"],"names":["createRawClient","result"],"mappings":";;;;;;;;;;;;;;;;;;AAgDA,MAAM,SAAA,GAAY,wCAAA;AAElB,MAAM,SAAA,GAAY,CAChB,kBAAA,EACA,SAAA,EACA,UAAA,KACsB;AACtB,EAAA,MAAM,SAAS,EAAC;AAChB,EAAA,MAAM,WAAA,GAAc,CAAC,QAAA,KACnB,IAAI,MAAM,MAAA,EAAQ;AAAA,IAChB,GAAA,CAAI,GAAG,IAAA,EAAM;AACX,MAAA,OAAO,SAAS,IAAc,CAAA;AAAA,IAChC;AAAA,GACD,CAAA;AACH,EAAA,MAAM,eAAA,GAAkB,CAAI,QAAA,KAA0C;AACpE,IAAA,MAAM,QAA2C,EAAC;AAClD,IAAA,OAAO,WAAA,CAAY,CAAC,CAAA,KAAM;AACxB,MAAA,IAAI,CAAC,KAAA,CAAM,CAAC,GAAG,KAAA,CAAM,CAAC,IAAI,EAAC;AAC3B,MAAA,OAAO,WAAA,CAAY,CAAC,CAAA,KAAM;AACxB,QAAA,IAAI,CAAC,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAA,EAAG,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,QAAA,CAAS,GAAG,CAAC,CAAA;AAC7C,QAAA,OAAO,KAAA,CAAM,CAAC,CAAA,CAAE,CAAC,CAAA;AAAA,MACnB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,GAAA,EAAqB,IAAA,KACtC,GAAA,CAAI,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,IAAI,CAAA;AAEzD,EAAA,MAAM,eAAA,GAAkB,kBAAA;AAAA,IACtB,SAAA,CAAU,aAAA;AAAA,IACV,SAAA,CAAU,QAAA;AAAA,IACV,SAAA,CAAU;AAAA,GACZ;AACA,EAAA,MAAM,KAAA,GAAQ,eAAA;AAAA,IAAgB,CAAC,QAAQ,IAAA,KACrC,kBAAA;AAAA,MACE,MAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA;AAAA,MACA,eAAA;AAAA,MACA,mBAAA;AAAA,QACE,kBAAA;AAAA,QACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,OAAA,EAAS,QAAQ,IAAI,CAAA;AAAA;AAAA,QAEnD,CAAC,GAAA,KAAQ;AACP,UAAA,MAAM,OAAO,SAAA,CAAU,GAAA,EAAK,MAAM,CAAA,EAAG,SAAS,KAAA,CAAM,IAAA;AAAA,YAClD,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS;AAAA,WACpB;AACA,UAAA,OAAO,IAAA,IAAQ,IAAA,GAAO,IAAA,GAAO,iBAAA,CAAkB,IAAI,CAAA;AAAA,QACrD;AAAA;AACF;AACF,GACF;AAEA,EAAA,MAAM,YAAA,GAAe,CACnB,GAAA,EACA,IAAA,EACA,IACA,IAAA,KACG;AACH,IAAA,IAAI,EAAA,IAAM,MAAM,OAAO,IAAA;AACvB,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA;AAC3B,IAAA,IAAI,MAAM,IAAA,KAAS,MAAA,EAAQ,MAAM,IAAI,MAAM,eAAe,CAAA;AAE1D,IAAA,IAAI,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,IAAK,MAAM,OAAO,IAAA;AACtC,IAAA,MAAM,IAAA,GAAO,uBAAA,CAAwB,KAAA,CAAM,KAAA,CAAM,IAAI,CAAC,CAAA;AACtD,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA,KAAS,MAAA,GAAS,IAAA,GAAO,kBAAA;AAAA,MAC/B,MAAA,EAAQ,IAAA,KAAS,MAAA,GAAS,kBAAA,GAAqB;AAAA,KACjD;AAAA,EACF,CAAA;AACA,EAAA,MAAM,EAAA,GAAK,eAAA;AAAA,IAAgB,CAAC,QAAQ,IAAA,KAClC,aAAA;AAAA,MACE,MAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAA;AAAA,MACA,mBAAA;AAAA,QACE,kBAAA;AAAA,QACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,EAAA,EAAI,QAAQ,IAAI,CAAA;AAAA,QAC9C,CAAC,GAAA,KACC,YAAA,CAAa,GAAA,EAAK,MAAA,EAAQ,SAAA,CAAU,GAAA,EAAK,MAAM,CAAA,EAAG,KAAA,EAAO,IAAA,EAAM,IAAI;AAAA,OACvE;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,MAAM,KAAA,GAAQ,eAAA;AAAA,IAAgB,CAAC,QAAQ,IAAA,KACrC,gBAAA;AAAA,MACE,MAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA;AAAA,MACA,mBAAA;AAAA,QACE,kBAAA;AAAA,QACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,KAAA,EAAO,QAAQ,IAAI,CAAA;AAAA,QACjD,CAAC,GAAA,KACC,YAAA;AAAA,UACE,GAAA;AAAA,UACA,QAAA;AAAA,UACA,SAAA,CAAU,GAAA,EAAK,MAAM,CAAA,EAAG,MAAA,EAAQ,IAAA;AAAA,UAChC;AAAA;AACF;AACJ;AACF,GACF;AAEA,EAAA,MAAM,SAAA,GAAY,eAAA;AAAA,IAAgB,CAAC,QAAQ,IAAA,KACzC,mBAAA;AAAA,MACE,MAAA;AAAA,MACA,IAAA;AAAA,MACA,mBAAA;AAAA,QACE,kBAAA;AAAA,QACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,KAAA,EAAO,QAAQ,IAAI,CAAA;AAAA,QACjD,CAAC,GAAA,KAAQ;AACP,UAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,EAAK,MAAM,GAAG,SAAA,CAAU,IAAA;AAAA,YAC7C,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS;AAAA,WACpB,EAAG,IAAA;AACH,UAAA,OAAO,IAAA,IAAQ,IAAA,GAAO,IAAA,GAAO,qBAAA,CAAsB,IAAI,CAAA;AAAA,QACzD;AAAA;AACF;AACF,GACF;AAEA,EAAA,MAAM,IAAA,GAAO,eAAA;AAAA,IAAgB,CAAC,KAAK,MAAA,KACjC,sBAAA;AAAA,MACE,GAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,mBAAA;AAAA,QACE,kBAAA;AAAA,QACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,GAAA,EAAK,KAAK,MAAM,CAAA;AAAA,QAC9C,CAAC,GAAA,KACC,qBAAA;AAAA,UACE,IAAI,MAAA,CAAO,QAAA,CAAS,IAAA,CACjB,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,GAAG,EAC1B,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,MAAM;AAAA;AAC1C;AACJ;AACF,GACF;AACA,EAAA,MAAM,IAAA,GAAO,eAAA;AAAA,IAAgB,CAAC,QAAQ,KAAA,KACpC,iBAAA;AAAA,MACE,MAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA;AAAA,MACA,mBAAA;AAAA,QACE,kBAAA;AAAA,QACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,OAAA,EAAS,QAAQ,KAAK,CAAA;AAAA,QACpD,CAAC,GAAA,KACC,qBAAA;AAAA,UACE,IAAI,MAAA,CAAO,QAAA,CAAS,OAAA,CACjB,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,MAAM,EAC7B,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,KAAK;AAAA;AACzC;AACJ;AACF,GACF;AAEA,EAAA,MAAM,WAAA,GAAc,CAClB,QAAA,EACA,KAAA,KACG;AACH,IAAA,MAAM,EAAE,MAAA,EAAQ,cAAA,KAAmB,mBAAA,CAAoB,KAAK,EAAE,OAAA,EAAQ;AACtE,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,eACb,eAAA,CAAgB,MAAA,CAAO,IAAK,CAAA,CAC5B,GAAA,CAAI,QAAA,CAAS,OAAA,EAAS,CAAA;AACzB,MAAA,MAAM,SAAS,OAAA,CAAQ,IAAA;AACvB,MAAA,MAAM,IAAA,GAAO,QAAQ,KAAA,CAAM,IAAA;AAC3B,MAAA,MAAM,IAAA,GAAO,QAAQ,KAAA,CAAM,KAAA;AAE3B,MAAA,OAAO,aAAA;AAAA,QACL,MAAA;AAAA,QACA,IAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA;AAAA,QACA,mBAAA;AAAA,UACE,kBAAA;AAAA,UACA,CAAC,CAAA,KAAM,CAAA,CAAE,cAAc,MAAA,CAAO,EAAA,EAAI,QAAQ,IAAI,CAAA;AAAA,UAC9C,CAAC,GAAA,KACC,YAAA;AAAA,YACE,GAAA;AAAA,YACA,MAAA;AAAA,YACA,SAAA,CAAU,GAAA,EAAK,MAAM,CAAA,EAAG,KAAA,EAAO,IAAA;AAAA,YAC/B;AAAA;AACF,SACJ;AAAA,QACA;AAAA,QACA,IAAI,CAAA;AAAA,IACR,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAAA,IAC/C;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,gBAAgB,CACd,QAAA,EACA,KAAA,KAEA,KAAA,GACI,YAAY,QAAA,EAAU,KAAK,CAAA,GAC3B,kBAAA,CAAmB,KAAK,CAAC,CAAA,KAAM,WAAA,CAAY,QAAA,EAAU,CAAC,CAAC,CAAA;AAAA,IAC7D,EAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;AA2CO,SAAS,aACd,QAAA,EACA,EAAE,aAAa,WAAA,EAAY,GAAyB,EAAC,EACrC;AAChB,EAAA,MAAM,SAAA,GAA6BA,eAAgB,QAAQ,CAAA;AAC3D,EAAA,MAAM,MAAA,GAAS,oBAAoB,SAAA,EAAW;AAAA,IAC5C,WAAA,EAAa,cACT,CAAC,QAAA,KAAqB,KAAK,WAAA,CAAY,QAAQ,CAAC,CAAA,GAChD,MAAA;AAAA,IACJ;AAAA,GACD,CAAA;AACD,EAAA,MAAM,EAAE,kBAAiB,GAAI,SAAA;AAE7B,EAAA,MAAM,EAAE,QAAA,EAAU,GAAG,UAAA,EAAW,GAAI,OAAO,UAAA,EAAW;AACtD,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,UAAA,CAAW,WAAW,CAAA;AACrD,EAAA,MAAM,SAAA,GAAwB;AAAA,IAC5B,GAAG,UAAA;AAAA,IACH,QAAA,EAAU,KAAA,CAAM,gBAAgB,CAAA,CAAE,IAAA;AAAA,MAChC,GAAA,CAAI,CAAC,EAAE,WAAA,OAAkB,WAAW,CAAA;AAAA,MACpC,UAAA,CAAW,MAAM,QAAQ,CAAA;AAAA,MACzB,YAAY,CAAC;AAAA,KACf;AAAA,IACA,QAAA,EAAU,WAAA,CAAY,UAAA,CAAW,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,IAC3D,KAAA,EAAO,WAAA,CAAY,UAAA,CAAW,KAAA,EAAO,QAAQ,KAAK,CAAA;AAAA,IAClD,KAAA,EAAO,WAAA,CAAY,UAAA,CAAW,KAAA,EAAO,QAAQ,KAAK,CAAA;AAAA,IAClD,OAAA,EAAS,WAAA,CAAY,UAAA,CAAW,OAAA,EAAS,QAAQ,OAAO,CAAA;AAAA,IACxD,SAAA,EAAW,WAAA,CAAY,UAAA,CAAW,SAAA,EAAW,QAAQ,SAAS,CAAA;AAAA,IAC9D,eAAA,EAAiB,WAAA;AAAA,MACf,UAAA,CAAW,eAAA;AAAA,MACX,OAAA,CAAQ;AAAA,KACV;AAAA,IACA,kBAAA,EAAoB,WAAA;AAAA,MAClB,UAAA,CAAW,kBAAA;AAAA,MACX,OAAA,CAAQ;AAAA;AACV,GACF;AAEA,EAAA,MAAM,WAGgB,SAAA,CAAU,OAAA;AAEhC,EAAA,IAAI,YAAA;AACJ,EAAA,MAAM,kBAAA,uBAAyB,OAAA,EAG7B;AACF,EAAA,MAAM,aAAA,GAAgB,CAAC,eAAA,KAAqC;AAC1D,IAAA,MAAMC,UACJ,kBAAA,CAAmB,GAAA,CAAI,eAAe,CAAA,IACtC,wBAAA,CAAyB,iBAAiB,SAAS,CAAA;AACrD,IAAA,kBAAA,CAAmB,GAAA,CAAI,iBAAiBA,OAAM,CAAA;AAC9C,IAAA,OAAOA,OAAAA;AAAA,EACT,CAAA;AACA,EAAA,MAAM,eAAA,GAAkB,MACrB,YAAA,KAAA,YAAA,GAAiB,kBAAA,CAAmB,SAAS,CAAA,CAAA;AAChD,EAAA,MAAM,EAAE,cAAa,GAAI,MAAA;AAEzB,EAAA,MAAM,YAAA,GAAe,CAAC,EAAA,KACpB,SAAA,CAAU,kBAAA,CAAmB,EAAE,CAAA,CAAE,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,WAAW,CAAC,CAAA;AAErE,EAAA,MAAM,MAAA,GAAyB;AAAA,IAC7B,gBAAA;AAAA,IAEA,YAAA;AAAA,IACA,WAAA,EAAa,CAAC,OAAA,EAAoB,MAAA,KAChC,yBAAyB,YAAA,CAAa,OAAO,GAAG,MAAM,CAAA;AAAA,IAExD,SAAS,SAAA,CAAU,UAAA;AAAA,IACnB,WAAW,CAAC,KAAA,KAAqB,SAAA,CAAU,SAAA,CAAU,OAAO,IAAI,CAAA;AAAA,IAEhE,iBAAiB,SAAA,CAAU,UAAA;AAAA,IAC3B,iBAAA,EAAmB,MAAM,cAAA,CAAe,SAAA,CAAU,UAAU,CAAA;AAAA,IAE5D,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,aAAA,EAAe,MAAM,cAAA,CAAe,SAAA,CAAU,WAAW,CAAA;AAAA,IAEzD,gBAAgB,SAAA,CAAU,KAAA;AAAA,IAC1B,cAAc,CAAC,IAAA,KAAiB,eAAe,SAAA,CAAU,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,IAEpE,cAAA,EAAgB,CAAC,IAAA,KACf,cAAA,CAAe,UAAU,OAAA,CAAQ,IAAA,IAAQ,IAAI,CAAC,CAAA;AAAA,IAEhD,QAAQ,CAAA,GAAI,IAAA,KAAS,OAAO,SAAA,EAAW,YAAA,EAAc,GAAG,IAAI,CAAA;AAAA,IAC5D,gBAAgB,CAAC,EAAA,KAAO,OAAA,CAAQ,SAAA,EAAW,cAAc,EAAE,CAAA;AAAA,IAE3D,WAAA,EAAa,CAA4B,eAAA,KAAuB;AAC9D,MAAA,MAAM,KAAA,GAAQ,cAAc,eAAe,CAAA;AAC3C,MAAA,OAAO,MAAA,CAAO,MAAA;AAAA,QACZ,SAAA,CAAoB,KAAA,EAAO,SAAA,EAAW,YAAY,CAAA;AAAA,QAClD,EAAE,oBAAoB,KAAA;AAAM,OAC9B;AAAA,IACF,CAAA;AAAA,IAEA,cAAc,MAAS;AACrB,MAAA,MAAM,QAAQ,eAAA,EAAgB;AAC9B,MAAA,OAAO,OAAO,MAAA,CAAO,SAAA,CAAmB,KAAA,EAAO,SAAA,EAAW,YAAY,CAAA,EAAG;AAAA,QACvE,YAAA,EAAc;AAAA,OACf,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,QAAA,EAAU,CAAC,GAAA,EAAK,EAAE,IAAI,MAAA,EAAO,GAAI,EAAC,KAChC,wBAAA;AAAA,MACE,SAAA,CAAU,QAAA,CAAS,EAAA,IAAM,IAAA,EAAM,SAAS,MAAM;AAC5C,QAAA,MAAM,GAAA,GAAM,GAAA,CAAI,KAAA,CAAM,SAAS,IAAI,CAAC,CAAA;AACpC,QAAA,OAAO,GAAA,GAAM,KAAK,GAAG,CAAA,CAAA,GAAK,OAAO,QAAA,CAAS,GAAG,EAAE,KAAA,EAAM;AAAA,MACvD,CAAC,CAAA;AAAA,MACD;AAAA,KACF;AAAA,IAEF,SAAS,MAAM;AACb,MAAA,SAAA,CAAU,QAAA,EAAS;AACnB,MAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,IACjB,CAAA;AAAA,IAEA;AAAA,GACF;AAEC,EAAC,OAAe,sBAAA,GAAyB,SAAA;AAE1C,EAAA,OAAO,MAAA;AACT;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { Binary, Blake2256 } from '@polkadot-api/substrate-bindings';
2
- import { lastValueFrom, take, mergeMap, map, catchError, of, merge, takeWhile, reduce, filter, Observable, concat, EMPTY, distinctUntilChanged } from 'rxjs';
2
+ import { lastValueFrom, defer, map, mergeMap, merge, filter, take, ignoreElements, Observable, concat, of, EMPTY, distinctUntilChanged } from 'rxjs';
3
3
  import '@polkadot-api/observable-client';
4
4
  import '../utils/shareLatest.mjs';
5
5
  import { toHex, fromHex } from '@polkadot-api/utils';
@@ -113,63 +113,39 @@ const submit$ = (chainHead, broadcastTx$, tx, emitSign = false) => {
113
113
  txHash,
114
114
  ...rest
115
115
  });
116
- const validate$ = chainHead.pinnedBlocks$.pipe(
117
- take(1),
118
- mergeMap((blocks) => {
119
- let bestBlocks = [];
120
- return blocks.finalizedRuntime.runtime.pipe(
121
- map((r) => r.getMortalityFromTx(tx)),
122
- catchError(() => of({ mortal: false })),
123
- map((x) => {
124
- const { best, finalized } = blocks;
125
- let current = best;
126
- while (current !== finalized) {
127
- bestBlocks.push(current);
128
- current = blocks.blocks.get(current).parent;
129
- }
130
- bestBlocks.push(finalized);
131
- if (!x.mortal) return [finalized, best];
132
- const { phase, period } = x;
133
- const bestBlock = blocks.blocks.get(best);
134
- const topNumber = bestBlock.number;
135
- const txBlockNumber = Math.floor((topNumber - phase) / period) * period + phase;
136
- let result = [blocks.blocks.get(blocks.finalized)];
137
- while (result.length && result[0].number < txBlockNumber) {
138
- result = result.flatMap((x2) => [...x2.children]).map((x2) => blocks.blocks.get(x2)).filter(Boolean);
139
- }
140
- return (result.length ? result : [bestBlock]).map((x2) => x2.hash);
141
- }),
142
- mergeMap(
143
- (toCheck) => merge(
144
- ...[...new Set(toCheck)].map(
145
- (at) => chainHead.validateTx$(at, tx).pipe(map((result) => ({ at, result })))
146
- )
147
- )
148
- ),
149
- takeWhile(({ result }) => !result.success, true),
150
- reduce(
151
- (acc, curr) => [...acc, curr],
152
- []
153
- ),
154
- map((results) => {
155
- const badOnes = new Map(
156
- results.filter(({ result }) => !result.success).map((x) => [x.at, x.result])
157
- );
158
- if (badOnes.size < results.length) return null;
159
- throw new InvalidTxError(
160
- badOnes.get(
161
- // there is a possible, but very unlikely, race-condition in which:
162
- // we have received a new block that is about to be flagged as best,
163
- // and that its height is higher than all the others, but the notification
164
- // that sets it as best has not arrived yet. In that case, that block wouldn't
165
- // be in the lineage of the best-blocks, but then it would be the only one in the list of `badOnes`
166
- bestBlocks.find((x) => badOnes.has(x)) ?? [...badOnes.keys()][0]
167
- ).value
168
- );
169
- }),
170
- filter(Boolean)
171
- );
172
- })
116
+ const pinnedBlocks = chainHead.pinnedBlocks$.state;
117
+ const getHeightFromMortality = (mortality) => {
118
+ if (!mortality.mortal) return 0;
119
+ const { phase, period } = mortality;
120
+ const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best).number;
121
+ return Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase;
122
+ };
123
+ const getTipsFromHeight = (height) => {
124
+ let tips = [...pinnedBlocks.blocks.values()].filter(
125
+ (block) => !block.unpinnable && !block.children.size
126
+ );
127
+ const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized);
128
+ tips = finalized.children ? [finalized, ...tips] : tips;
129
+ return tips.filter((x) => x.number >= height);
130
+ };
131
+ const validateTxAt$ = ({ hash }) => chainHead.validateTx$(hash, tx);
132
+ const validate$ = defer(
133
+ () => pinnedBlocks.finalizedRuntime.runtime.pipe(
134
+ map((r) => r.getMortalityFromTx(tx)),
135
+ map(getHeightFromMortality),
136
+ map(getTipsFromHeight),
137
+ mergeMap(
138
+ (blocksToValidate) => merge(...blocksToValidate.map(validateTxAt$)).pipe(
139
+ filter(({ success, value }, idx) => {
140
+ if (!success && idx === blocksToValidate.length - 1)
141
+ throw new InvalidTxError(value);
142
+ return success;
143
+ }),
144
+ take(1)
145
+ )
146
+ ),
147
+ ignoreElements()
148
+ )
173
149
  );
174
150
  const track$ = new Observable((observer) => {
175
151
  const subscription = chainHead.trackTx$(tx).subscribe(observer);
@@ -1 +1 @@
1
- {"version":3,"file":"submit-fns.mjs","sources":["../../../src/tx/submit-fns.ts"],"sourcesContent":["import {\n Binary,\n Blake2256,\n HexString,\n ResultPayload,\n} from \"@polkadot-api/substrate-bindings\"\nimport {\n EMPTY,\n Observable,\n catchError,\n concat,\n distinctUntilChanged,\n filter,\n lastValueFrom,\n map,\n merge,\n mergeMap,\n of,\n reduce,\n take,\n takeWhile,\n} from \"rxjs\"\nimport {\n ChainHead$,\n PinnedBlocks,\n SystemEvent,\n} from \"@polkadot-api/observable-client\"\nimport { AnalyzedBlock } from \"@polkadot-api/observable-client\"\nimport { TxEvent, TxEventsPayload, TxFinalizedPayload } from \"./types\"\nimport { continueWith } from \"@/utils\"\nimport { fromHex, toHex } from \"@polkadot-api/utils\"\n\n// TODO: make it dynamic based on the tx-function of the client\nconst hashFromTx = (tx: HexString) => toHex(Blake2256(fromHex(tx)))\n\nconst computeState = (\n analized$: Observable<AnalyzedBlock>,\n blocks$: Observable<PinnedBlocks>,\n) =>\n new Observable<\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n >((observer) => {\n const analyzedBlocks = new Map<string, AnalyzedBlock>()\n let pinnedBlocks: PinnedBlocks\n let latestState:\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n\n const computeNextState = () => {\n let current: string = pinnedBlocks.best\n let analyzed: AnalyzedBlock | undefined = analyzedBlocks.get(current)\n let analyzedNumber = pinnedBlocks.blocks.get(current)!.number\n\n while (!analyzed) {\n const block = pinnedBlocks.blocks.get(current)\n if (!block) break\n analyzed = analyzedBlocks.get((current = block.parent))\n analyzedNumber--\n }\n\n if (!analyzed) return // this shouldn't happen, though\n\n const isFinalized =\n analyzedNumber <=\n pinnedBlocks.blocks.get(pinnedBlocks.finalized)!.number\n\n const found = analyzed.found.type\n if (found && latestState?.found && latestState.hash === analyzed.hash) {\n if (isFinalized) observer.complete()\n return\n }\n\n observer.next(\n (latestState = analyzed.found.type\n ? {\n found: found as true,\n hash: analyzed.hash,\n number: analyzedNumber,\n index: analyzed.found.index,\n events: analyzed.found.events,\n }\n : {\n found: found as false,\n validity: analyzed.found.validity,\n }),\n )\n\n if (isFinalized) {\n if (found) observer.complete()\n else if (analyzed.found.validity?.success === false)\n observer.error(new InvalidTxError(analyzed.found.validity.value))\n }\n }\n\n const subscription = blocks$\n .pipe(\n distinctUntilChanged(\n (a, b) => a.finalized === b.finalized && a.best === b.best,\n ),\n )\n .subscribe({\n next: (pinned: PinnedBlocks) => {\n pinnedBlocks = pinned\n if (analyzedBlocks.size === 0) return\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n })\n\n subscription.add(\n analized$.subscribe({\n next: (block) => {\n analyzedBlocks.set(block.hash, block)\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n }),\n )\n\n return subscription\n }).pipe(distinctUntilChanged((a, b) => a === b))\n\nconst getTxSuccessFromSystemEvents = (\n systemEvents: Array<SystemEvent>,\n txIdx: number,\n): Omit<TxEventsPayload, \"block\"> => {\n const events = systemEvents\n .filter((x) => x.phase.type === \"ApplyExtrinsic\" && x.phase.value === txIdx)\n .map((x) => ({ ...x.event, topics: x.topics }))\n\n const lastEvent = events[events.length - 1]\n if (\n lastEvent.type === \"System\" &&\n lastEvent.value.type === \"ExtrinsicFailed\"\n ) {\n return {\n ok: false,\n events,\n dispatchError: lastEvent.value.value.dispatch_error,\n }\n }\n\n return { ok: true, events }\n}\n\n/*\ntype TransactionValidityError = Enum<{\n Invalid: Enum<{\n Call: undefined\n Payment: undefined\n Future: undefined\n Stale: undefined\n BadProof: undefined\n AncientBirthBlock: undefined\n ExhaustsResources: undefined\n Custom: number\n BadMandatory: undefined\n MandatoryValidation: undefined\n BadSigner: undefined\n }>\n Unknown: Enum<{\n CannotLookup: undefined\n NoUnsignedValidator: undefined\n Custom: number\n }>\n}>\n*/\n\nexport class InvalidTxError extends Error {\n error: any // likely to be a `TransactionValidityError`\n constructor(e: any) {\n super(\n JSON.stringify(\n e,\n (_, value) => {\n if (typeof value === \"bigint\") return value.toString()\n return value instanceof Binary ? value.asHex() : value\n },\n 2,\n ),\n )\n this.name = \"InvalidTxError\"\n this.error = e\n }\n}\n\nexport const submit$ = (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n tx: HexString,\n emitSign = false,\n): Observable<TxEvent> => {\n const txHash = hashFromTx(tx)\n const getTxEvent = <\n Type extends TxEvent[\"type\"],\n Rest extends Omit<TxEvent & { type: Type }, \"type\" | \"txHash\">,\n >(\n type: Type,\n rest: Rest,\n ): TxEvent & { type: Type } =>\n ({\n type,\n txHash,\n ...rest,\n }) as any\n\n const validate$ = chainHead.pinnedBlocks$.pipe(\n take(1),\n mergeMap((blocks) => {\n let bestBlocks: string[] = []\n return blocks.finalizedRuntime.runtime.pipe(\n map((r) => r.getMortalityFromTx(tx)),\n catchError(() => of({ mortal: false as const })),\n map((x) => {\n const { best, finalized } = blocks\n\n // before we start doing async stuff, we must \"take a picture\"\n // of the current lineage of best-blocks\n let current = best\n while (current !== finalized) {\n bestBlocks.push(current)\n current = blocks.blocks.get(current)!.parent\n }\n bestBlocks.push(finalized)\n\n if (!x.mortal) return [finalized, best]\n\n const { phase, period } = x\n const bestBlock = blocks.blocks.get(best)!\n const topNumber = bestBlock.number\n const txBlockNumber =\n Math.floor((topNumber - phase) / period) * period + phase\n\n let result = [blocks.blocks.get(blocks.finalized)!]\n while (result.length && result[0].number < txBlockNumber) {\n result = result\n .flatMap((x) => [...x.children])\n .map((x) => blocks.blocks.get(x)!)\n .filter(Boolean)\n }\n return (result.length ? result : [bestBlock]).map((x) => x.hash)\n }),\n mergeMap((toCheck) =>\n merge(\n ...[...new Set(toCheck)].map((at) =>\n chainHead\n .validateTx$(at, tx)\n .pipe(map((result) => ({ at, result }))),\n ),\n ),\n ),\n takeWhile(({ result }) => !result.success, true),\n reduce(\n (acc, curr) => [...acc, curr],\n [] as { at: string; result: ResultPayload<any, any> }[],\n ),\n map((results) => {\n const badOnes = new Map(\n results\n .filter(({ result }) => !result.success)\n .map((x) => [x.at, x.result]),\n )\n if (badOnes.size < results.length) return null\n\n throw new InvalidTxError(\n badOnes.get(\n // there is a possible, but very unlikely, race-condition in which:\n // we have received a new block that is about to be flagged as best,\n // and that its height is higher than all the others, but the notification\n // that sets it as best has not arrived yet. In that case, that block wouldn't\n // be in the lineage of the best-blocks, but then it would be the only one in the list of `badOnes`\n bestBlocks.find((x) => badOnes.has(x)) ?? [...badOnes.keys()][0],\n )!.value,\n )\n }),\n filter(Boolean),\n )\n }),\n )\n\n const track$ = new Observable<AnalyzedBlock>((observer) => {\n const subscription = chainHead.trackTx$(tx).subscribe(observer)\n subscription.add(\n broadcastTx$(tx).subscribe({\n error(e) {\n observer.error(e)\n },\n }),\n )\n return subscription\n })\n\n const bestBlockState$ = computeState(track$, chainHead.pinnedBlocks$).pipe(\n map((x) => {\n if (!x.found)\n return getTxEvent(\"txBestBlocksState\", {\n found: false,\n isValid: x.validity?.success !== false,\n })\n\n return getTxEvent(\"txBestBlocksState\", {\n found: true,\n block: {\n index: x.index,\n number: x.number,\n hash: x.hash,\n },\n ...getTxSuccessFromSystemEvents(x.events, x.index),\n })\n }),\n )\n\n return concat(\n emitSign ? of(getTxEvent(\"signed\", {})) : EMPTY,\n validate$,\n of(getTxEvent(\"broadcasted\", {})),\n bestBlockState$.pipe(\n continueWith(({ found, type, ...rest }) =>\n found ? of(getTxEvent(\"finalized\", rest as any)) : EMPTY,\n ),\n ),\n )\n}\n\nexport const submit = async (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n transaction: HexString,\n _at?: HexString,\n): Promise<TxFinalizedPayload> =>\n lastValueFrom(submit$(chainHead, broadcastTx$, transaction)).then((x) => {\n if (x.type !== \"finalized\") throw null\n const result: TxFinalizedPayload = { ...x }\n delete (result as any).type\n return result\n })\n"],"names":["x"],"mappings":"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"}
1
+ {"version":3,"file":"submit-fns.mjs","sources":["../../../src/tx/submit-fns.ts"],"sourcesContent":["import {\n Binary,\n Blake2256,\n HexString,\n ResultPayload,\n} from \"@polkadot-api/substrate-bindings\"\nimport {\n EMPTY,\n Observable,\n concat,\n defer,\n distinctUntilChanged,\n filter,\n ignoreElements,\n lastValueFrom,\n map,\n merge,\n mergeMap,\n of,\n take,\n} from \"rxjs\"\nimport {\n BlockInfo,\n ChainHead$,\n PinnedBlocks,\n SystemEvent,\n} from \"@polkadot-api/observable-client\"\nimport { AnalyzedBlock } from \"@polkadot-api/observable-client\"\nimport { TxEvent, TxEventsPayload, TxFinalizedPayload } from \"./types\"\nimport { continueWith } from \"@/utils\"\nimport { fromHex, toHex } from \"@polkadot-api/utils\"\n\n// TODO: make it dynamic based on the tx-function of the client\nconst hashFromTx = (tx: HexString) => toHex(Blake2256(fromHex(tx)))\n\nconst computeState = (\n analized$: Observable<AnalyzedBlock>,\n blocks$: Observable<PinnedBlocks>,\n) =>\n new Observable<\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n >((observer) => {\n const analyzedBlocks = new Map<string, AnalyzedBlock>()\n let pinnedBlocks: PinnedBlocks\n let latestState:\n | {\n found: true\n hash: string\n number: number\n index: number\n events: any\n }\n | { found: false; validity: ResultPayload<any, any> | null }\n\n const computeNextState = () => {\n let current: string = pinnedBlocks.best\n let analyzed: AnalyzedBlock | undefined = analyzedBlocks.get(current)\n let analyzedNumber = pinnedBlocks.blocks.get(current)!.number\n\n while (!analyzed) {\n const block = pinnedBlocks.blocks.get(current)\n if (!block) break\n analyzed = analyzedBlocks.get((current = block.parent))\n analyzedNumber--\n }\n\n if (!analyzed) return // this shouldn't happen, though\n\n const isFinalized =\n analyzedNumber <=\n pinnedBlocks.blocks.get(pinnedBlocks.finalized)!.number\n\n const found = analyzed.found.type\n if (found && latestState?.found && latestState.hash === analyzed.hash) {\n if (isFinalized) observer.complete()\n return\n }\n\n observer.next(\n (latestState = analyzed.found.type\n ? {\n found: found as true,\n hash: analyzed.hash,\n number: analyzedNumber,\n index: analyzed.found.index,\n events: analyzed.found.events,\n }\n : {\n found: found as false,\n validity: analyzed.found.validity,\n }),\n )\n\n if (isFinalized) {\n if (found) observer.complete()\n else if (analyzed.found.validity?.success === false)\n observer.error(new InvalidTxError(analyzed.found.validity.value))\n }\n }\n\n const subscription = blocks$\n .pipe(\n distinctUntilChanged(\n (a, b) => a.finalized === b.finalized && a.best === b.best,\n ),\n )\n .subscribe({\n next: (pinned: PinnedBlocks) => {\n pinnedBlocks = pinned\n if (analyzedBlocks.size === 0) return\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n })\n\n subscription.add(\n analized$.subscribe({\n next: (block) => {\n analyzedBlocks.set(block.hash, block)\n computeNextState()\n },\n error(e) {\n observer.error(e)\n },\n }),\n )\n\n return subscription\n }).pipe(distinctUntilChanged((a, b) => a === b))\n\nconst getTxSuccessFromSystemEvents = (\n systemEvents: Array<SystemEvent>,\n txIdx: number,\n): Omit<TxEventsPayload, \"block\"> => {\n const events = systemEvents\n .filter((x) => x.phase.type === \"ApplyExtrinsic\" && x.phase.value === txIdx)\n .map((x) => ({ ...x.event, topics: x.topics }))\n\n const lastEvent = events[events.length - 1]\n if (\n lastEvent.type === \"System\" &&\n lastEvent.value.type === \"ExtrinsicFailed\"\n ) {\n return {\n ok: false,\n events,\n dispatchError: lastEvent.value.value.dispatch_error,\n }\n }\n\n return { ok: true, events }\n}\n\n/*\ntype TransactionValidityError = Enum<{\n Invalid: Enum<{\n Call: undefined\n Payment: undefined\n Future: undefined\n Stale: undefined\n BadProof: undefined\n AncientBirthBlock: undefined\n ExhaustsResources: undefined\n Custom: number\n BadMandatory: undefined\n MandatoryValidation: undefined\n BadSigner: undefined\n }>\n Unknown: Enum<{\n CannotLookup: undefined\n NoUnsignedValidator: undefined\n Custom: number\n }>\n}>\n*/\nexport class InvalidTxError extends Error {\n error: any // likely to be a `TransactionValidityError`\n constructor(e: any) {\n super(\n JSON.stringify(\n e,\n (_, value) => {\n if (typeof value === \"bigint\") return value.toString()\n return value instanceof Binary ? value.asHex() : value\n },\n 2,\n ),\n )\n this.name = \"InvalidTxError\"\n this.error = e\n }\n}\n\nexport const submit$ = (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n tx: HexString,\n emitSign = false,\n): Observable<TxEvent> => {\n const txHash = hashFromTx(tx)\n const getTxEvent = <\n Type extends TxEvent[\"type\"],\n Rest extends Omit<TxEvent & { type: Type }, \"type\" | \"txHash\">,\n >(\n type: Type,\n rest: Rest,\n ): TxEvent & { type: Type } =>\n ({\n type,\n txHash,\n ...rest,\n }) as any\n\n const pinnedBlocks = chainHead.pinnedBlocks$.state\n const getHeightFromMortality = (\n mortality:\n | {\n mortal: false\n }\n | {\n mortal: true\n period: number\n phase: number\n },\n ) => {\n if (!mortality.mortal) return 0\n const { phase, period } = mortality\n const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best)!.number\n return (\n Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase\n )\n }\n\n const getTipsFromHeight = (height: number): BlockInfo[] => {\n let tips: BlockInfo[] = [...pinnedBlocks.blocks.values()].filter(\n (block) => !block.unpinnable && !block.children.size,\n )\n const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized)!\n tips = finalized.children ? [finalized, ...tips] : tips\n\n return tips.filter((x) => x.number >= height)\n }\n\n const validateTxAt$ = ({ hash }: BlockInfo) => chainHead.validateTx$(hash, tx)\n const validate$: Observable<never> = defer(() =>\n pinnedBlocks.finalizedRuntime.runtime.pipe(\n map((r) => r.getMortalityFromTx(tx)),\n map(getHeightFromMortality),\n map(getTipsFromHeight),\n mergeMap((blocksToValidate) =>\n merge(...blocksToValidate.map(validateTxAt$)).pipe(\n filter(({ success, value }, idx) => {\n if (!success && idx === blocksToValidate.length - 1)\n throw new InvalidTxError(value)\n return success\n }),\n take(1),\n ),\n ),\n ignoreElements(),\n ),\n )\n\n const track$ = new Observable<AnalyzedBlock>((observer) => {\n const subscription = chainHead.trackTx$(tx).subscribe(observer)\n subscription.add(\n broadcastTx$(tx).subscribe({\n error(e) {\n observer.error(e)\n },\n }),\n )\n return subscription\n })\n\n const bestBlockState$ = computeState(track$, chainHead.pinnedBlocks$).pipe(\n map((x) => {\n if (!x.found)\n return getTxEvent(\"txBestBlocksState\", {\n found: false,\n isValid: x.validity?.success !== false,\n })\n\n return getTxEvent(\"txBestBlocksState\", {\n found: true,\n block: {\n index: x.index,\n number: x.number,\n hash: x.hash,\n },\n ...getTxSuccessFromSystemEvents(x.events, x.index),\n })\n }),\n )\n\n return concat(\n emitSign ? of(getTxEvent(\"signed\", {})) : EMPTY,\n validate$,\n of(getTxEvent(\"broadcasted\", {})),\n bestBlockState$.pipe(\n continueWith(({ found, type, ...rest }) =>\n found ? of(getTxEvent(\"finalized\", rest as any)) : EMPTY,\n ),\n ),\n )\n}\n\nexport const submit = async (\n chainHead: ChainHead$,\n broadcastTx$: (tx: string) => Observable<never>,\n transaction: HexString,\n _at?: HexString,\n): Promise<TxFinalizedPayload> =>\n lastValueFrom(submit$(chainHead, broadcastTx$, transaction)).then((x) => {\n if (x.type !== \"finalized\") throw null\n const result: TxFinalizedPayload = { ...x }\n delete (result as any).type\n return result\n })\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -923,6 +923,22 @@ interface PolkadotClient {
923
923
  * spec](https://paritytech.github.io/json-rpc-interface-spec/api/chainSpec.html)
924
924
  */
925
925
  getChainSpecData: () => Promise<ChainSpecData>;
926
+ /**
927
+ * Retrieves the most modern stable version of the metadata for a given block.
928
+ *
929
+ * @param atBlock The block-hash of the block.
930
+ * @returns Observable that emits the most modern stable version of the
931
+ * metadata, and immediately completes.
932
+ */
933
+ getMetadata$: (atBlock: HexString) => Observable<Uint8Array>;
934
+ /**
935
+ * Retrieves the most modern stable version of the metadata for a given block.
936
+ *
937
+ * @param atBlock The block-hash of the block.
938
+ * @returns An abortable Promise that resolves into the most modern
939
+ * stable version of the metadata.
940
+ */
941
+ getMetadata: (atBlock: HexString, signal?: AbortSignal) => Promise<Uint8Array>;
926
942
  /**
927
943
  * Observable that emits `BlockInfo` for every new finalized block. It's a
928
944
  * multicast and stateful observable, that will synchronously replay its
package/dist/index.js CHANGED
@@ -961,63 +961,39 @@ const submit$ = (chainHead, broadcastTx$, tx, emitSign = false) => {
961
961
  txHash,
962
962
  ...rest
963
963
  });
964
- const validate$ = chainHead.pinnedBlocks$.pipe(
965
- rxjs.take(1),
966
- rxjs.mergeMap((blocks) => {
967
- let bestBlocks = [];
968
- return blocks.finalizedRuntime.runtime.pipe(
969
- rxjs.map((r) => r.getMortalityFromTx(tx)),
970
- rxjs.catchError(() => rxjs.of({ mortal: false })),
971
- rxjs.map((x) => {
972
- const { best, finalized } = blocks;
973
- let current = best;
974
- while (current !== finalized) {
975
- bestBlocks.push(current);
976
- current = blocks.blocks.get(current).parent;
977
- }
978
- bestBlocks.push(finalized);
979
- if (!x.mortal) return [finalized, best];
980
- const { phase, period } = x;
981
- const bestBlock = blocks.blocks.get(best);
982
- const topNumber = bestBlock.number;
983
- const txBlockNumber = Math.floor((topNumber - phase) / period) * period + phase;
984
- let result = [blocks.blocks.get(blocks.finalized)];
985
- while (result.length && result[0].number < txBlockNumber) {
986
- result = result.flatMap((x2) => [...x2.children]).map((x2) => blocks.blocks.get(x2)).filter(Boolean);
987
- }
988
- return (result.length ? result : [bestBlock]).map((x2) => x2.hash);
989
- }),
990
- rxjs.mergeMap(
991
- (toCheck) => rxjs.merge(
992
- ...[...new Set(toCheck)].map(
993
- (at) => chainHead.validateTx$(at, tx).pipe(rxjs.map((result) => ({ at, result })))
994
- )
995
- )
996
- ),
997
- rxjs.takeWhile(({ result }) => !result.success, true),
998
- rxjs.reduce(
999
- (acc, curr) => [...acc, curr],
1000
- []
1001
- ),
1002
- rxjs.map((results) => {
1003
- const badOnes = new Map(
1004
- results.filter(({ result }) => !result.success).map((x) => [x.at, x.result])
1005
- );
1006
- if (badOnes.size < results.length) return null;
1007
- throw new InvalidTxError(
1008
- badOnes.get(
1009
- // there is a possible, but very unlikely, race-condition in which:
1010
- // we have received a new block that is about to be flagged as best,
1011
- // and that its height is higher than all the others, but the notification
1012
- // that sets it as best has not arrived yet. In that case, that block wouldn't
1013
- // be in the lineage of the best-blocks, but then it would be the only one in the list of `badOnes`
1014
- bestBlocks.find((x) => badOnes.has(x)) ?? [...badOnes.keys()][0]
1015
- ).value
1016
- );
1017
- }),
1018
- rxjs.filter(Boolean)
1019
- );
1020
- })
964
+ const pinnedBlocks = chainHead.pinnedBlocks$.state;
965
+ const getHeightFromMortality = (mortality) => {
966
+ if (!mortality.mortal) return 0;
967
+ const { phase, period } = mortality;
968
+ const topNumber = pinnedBlocks.blocks.get(pinnedBlocks.best).number;
969
+ return Math.floor((Math.max(topNumber, phase) - phase) / period) * period + phase;
970
+ };
971
+ const getTipsFromHeight = (height) => {
972
+ let tips = [...pinnedBlocks.blocks.values()].filter(
973
+ (block) => !block.unpinnable && !block.children.size
974
+ );
975
+ const finalized = pinnedBlocks.blocks.get(pinnedBlocks.finalized);
976
+ tips = finalized.children ? [finalized, ...tips] : tips;
977
+ return tips.filter((x) => x.number >= height);
978
+ };
979
+ const validateTxAt$ = ({ hash }) => chainHead.validateTx$(hash, tx);
980
+ const validate$ = rxjs.defer(
981
+ () => pinnedBlocks.finalizedRuntime.runtime.pipe(
982
+ rxjs.map((r) => r.getMortalityFromTx(tx)),
983
+ rxjs.map(getHeightFromMortality),
984
+ rxjs.map(getTipsFromHeight),
985
+ rxjs.mergeMap(
986
+ (blocksToValidate) => rxjs.merge(...blocksToValidate.map(validateTxAt$)).pipe(
987
+ rxjs.filter(({ success, value }, idx) => {
988
+ if (!success && idx === blocksToValidate.length - 1)
989
+ throw new InvalidTxError(value);
990
+ return success;
991
+ }),
992
+ rxjs.take(1)
993
+ )
994
+ ),
995
+ rxjs.ignoreElements()
996
+ )
1021
997
  );
1022
998
  const track$ = new rxjs.Observable((observer) => {
1023
999
  const subscription = chainHead.trackTx$(tx).subscribe(observer);
@@ -1727,14 +1703,17 @@ function createClient(provider, { getMetadata, setMetadata } = {}) {
1727
1703
  let runtimeToken;
1728
1704
  const compatibilityToken = /* @__PURE__ */ new WeakMap();
1729
1705
  const getChainToken = (chainDefinition) => {
1730
- const result = compatibilityToken.get(chainDefinition) || createCompatibilityToken(chainDefinition, chainHead);
1731
- compatibilityToken.set(chainDefinition, result);
1732
- return result;
1706
+ const result2 = compatibilityToken.get(chainDefinition) || createCompatibilityToken(chainDefinition, chainHead);
1707
+ compatibilityToken.set(chainDefinition, result2);
1708
+ return result2;
1733
1709
  };
1734
1710
  const getRuntimeToken = () => runtimeToken ?? (runtimeToken = createRuntimeToken(chainHead));
1735
1711
  const { broadcastTx$ } = client;
1736
- return {
1712
+ const getMetadata$ = (at) => chainHead.getRuntimeContext$(at).pipe(rxjs.map((ctx) => ctx.metadataRaw));
1713
+ const result = {
1737
1714
  getChainSpecData,
1715
+ getMetadata$,
1716
+ getMetadata: (atBlock, signal) => firstValueFromWithSignal(getMetadata$(atBlock), signal),
1738
1717
  blocks$: chainHead.newBlocks$,
1739
1718
  hodlBlock: (block) => chainHead.holdBlock(block, true),
1740
1719
  finalizedBlock$: chainHead.finalized$,
@@ -1772,6 +1751,8 @@ function createClient(provider, { getMetadata, setMetadata } = {}) {
1772
1751
  },
1773
1752
  _request
1774
1753
  };
1754
+ result.___INTERNAL_DO_NOT_USE = chainHead;
1755
+ return result;
1775
1756
  }
1776
1757
 
1777
1758
  const createOfflineTxEntry = (pallet, name, metadataRaw, dynamicBuilder, signExtensionCreator) => {