From 60188ccec4d6f2ecdf8c8a73bd9d829a4aeeb5f0 Mon Sep 17 00:00:00 2001 From: Victor Oliva Date: Sun, 3 Nov 2024 11:35:24 +0100 Subject: [PATCH] refactor: move chain subscription up top, reuse dynamicBuilder --- src/chain.state.ts | 67 +++++++++++-------- .../LookupTypeEdit/LookupTypeEdit.tsx | 11 ++- src/main.tsx | 22 ++++-- src/pages/Constants.tsx | 14 ++-- src/pages/Explorer/BlockPopover.tsx | 12 ++-- src/pages/Explorer/BlockTable.tsx | 8 +-- src/pages/Explorer/BlockTime.tsx | 14 ++-- src/pages/Explorer/Detail/BlockDetail.tsx | 8 ++- src/pages/Explorer/Detail/extrinsicDecoder.ts | 7 +- src/pages/Explorer/Explorer.tsx | 46 ++++++------- src/pages/Explorer/Summary.tsx | 4 +- src/pages/Explorer/block.state.ts | 12 +--- src/pages/Explorer/index.ts | 3 + src/pages/Extrinsics/Extrinsics.tsx | 19 +++--- src/pages/RuntimeCalls/RuntimeCallQuery.tsx | 5 +- src/pages/Storage/StorageDecode.tsx | 11 ++- src/pages/Storage/StorageQuery.tsx | 35 +++++----- src/pages/Storage/StorageSubscriptions.tsx | 11 +-- 18 files changed, 149 insertions(+), 160 deletions(-) diff --git a/src/chain.state.ts b/src/chain.state.ts index cdc9e38..c1a1eaa 100644 --- a/src/chain.state.ts +++ b/src/chain.state.ts @@ -1,4 +1,5 @@ -import { getLookupFn } from "@polkadot-api/metadata-builders" +import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders" +import { getObservableClient } from "@polkadot-api/observable-client" import { Binary, CodecType, @@ -7,9 +8,9 @@ import { V14, V15, } from "@polkadot-api/substrate-bindings" -import { toHex } from "@polkadot-api/utils" import { createClient as createSubstrateClient } from "@polkadot-api/substrate-client" -import { shareLatest } from "@react-rxjs/core" +import { toHex } from "@polkadot-api/utils" +import { state } from "@react-rxjs/core" import { createClient, PolkadotClient } from "polkadot-api" import { chainSpec } from "polkadot-api/chains/polkadot" import { withLogsRecorder } from "polkadot-api/logs-provider" @@ -26,12 +27,10 @@ import { map, NEVER, of, - shareReplay, startWith, switchMap, tap, } from "rxjs" -import { getObservableClient } from "@polkadot-api/observable-client" export type ChainSource = { id: string } & ( | { @@ -55,30 +54,39 @@ const selectedSource$ = of({ type AnyMetadata = CodecType -export const chainClient$ = selectedSource$.pipe( - map((src) => [src.id, getProvider(src)] as const), - switchMap(([id, provider]) => { - const client = createClient(provider) - const substrateClient = createSubstrateClient(provider) - const observableClient = getObservableClient(substrateClient) - return concat( - of({ id, client, substrateClient, observableClient }), - NEVER, - ).pipe( - finalize(() => { - client.destroy() - observableClient.destroy() - }), - ) - }), - shareLatest(), +export const chainClient$ = state( + selectedSource$.pipe( + map((src) => [src.id, getProvider(src)] as const), + switchMap(([id, provider]) => { + const client = createClient(provider) + const substrateClient = createSubstrateClient(provider) + const observableClient = getObservableClient(substrateClient) + return concat( + of({ id, client, substrateClient, observableClient }), + NEVER, + ).pipe( + finalize(() => { + client.destroy() + observableClient.destroy() + }), + ) + }), + ), ) -export const unsafeApi$ = chainClient$.pipe( - map(({ client }) => client.getUnsafeApi()), - shareLatest(), +export const chainHead$ = state( + chainClient$.pipe( + switchMap(({ observableClient }) => { + const chainHead = observableClient.chainHead$() + return concat(of(chainHead), NEVER).pipe(finalize(chainHead.unfollow)) + }), + ), ) -export const metadata$ = chainClient$.pipe( +export const unsafeApi$ = chainClient$.pipeState( + map(({ client }) => client.getUnsafeApi()), +) + +export const metadata$ = chainClient$.pipeState( switchMap(({ id, client }) => { const metadata = from(getMetadata(client)).pipe( tap((v) => { @@ -98,9 +106,12 @@ export const metadata$ = chainClient$.pipe( } throw new Error("Incompatible metadata") }), - shareReplay(1), ) -export const lookup$ = metadata$.pipe(map(getLookupFn), shareLatest()) +export const lookup$ = metadata$.pipeState(map(getLookupFn)) + +export const dynamicBuilder$ = lookup$.pipeState( + map((lookup) => ({ lookup, ...getDynamicBuilder(lookup) })), +) async function getMetadata(client: PolkadotClient): Promise { const unsafeApi = client.getUnsafeApi() diff --git a/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx b/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx index 7a9f2c7..0289b8c 100644 --- a/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx +++ b/src/codec-components/LookupTypeEdit/LookupTypeEdit.tsx @@ -1,7 +1,6 @@ -import { lookup$ } from "@/chain.state" +import { dynamicBuilder$ } from "@/chain.state" import { byteArraysAreEqual } from "@/utils/byteArray" import { CodecComponentType, CodecComponentValue } from "@codec-components" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable } from "@react-rxjs/core" import { Codec } from "polkadot-api" import { ComponentProps, FC, useEffect, useRef, useState } from "react" @@ -19,10 +18,10 @@ import { BinaryDisplay } from "./BinaryDisplay" import { FocusPath } from "./FocusPath" const editTypeMetadataProps$ = state( - lookup$.pipe( - map((lookup) => ({ - metadata: lookup.metadata, - builder: getDynamicBuilder(lookup), + dynamicBuilder$.pipe( + map((builder) => ({ + builder, + metadata: builder.lookup.metadata, })), ), null, diff --git a/src/main.tsx b/src/main.tsx index 8186586..9c621ba 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,16 +1,24 @@ +import { RemoveSubscribe, Subscribe } from "@react-rxjs/core" import { StrictMode } from "react" import { createRoot } from "react-dom/client" import { BrowserRouter } from "react-router-dom" +import { merge } from "rxjs" import App from "./App.tsx" +import { dynamicBuilder$ } from "./chain.state.ts" import { TooltipProvider } from "./components/Tooltip.tsx" import "./index.css" +import { explorer$ } from "./pages/Explorer" createRoot(document.getElementById("root")!).render( - - - - - - - , + + + + + + + + + + + , ) diff --git a/src/pages/Constants.tsx b/src/pages/Constants.tsx index fe62266..18d0128 100644 --- a/src/pages/Constants.tsx +++ b/src/pages/Constants.tsx @@ -1,11 +1,12 @@ -import { lookup$ } from "@/chain.state" +import { dynamicBuilder$, lookup$ } from "@/chain.state" import { ViewCodec } from "@/codec-components/ViewCodec" import { ButtonGroup } from "@/components/ButtonGroup" +import { DocsRenderer } from "@/components/DocsRenderer" import { ExpandBtn } from "@/components/Expand" +import { Tooltip } from "@/components/Tooltip" import { withSubscribe } from "@/components/withSuspense" import { CodecComponentType } from "@/lib/codecComponents" import { getTypeComplexity } from "@/utils/shape" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable } from "@react-rxjs/core" import { Dot } from "lucide-react" import { HexString } from "polkadot-api" @@ -13,8 +14,6 @@ import { FC, useState } from "react" import { map } from "rxjs" import { twMerge } from "tailwind-merge" import { ValueDisplay } from "./Storage/StorageSubscriptions" -import { Tooltip } from "@/components/Tooltip" -import { DocsRenderer } from "@/components/DocsRenderer" const metadataConstants$ = state( lookup$.pipe( @@ -76,8 +75,11 @@ const PalletConstants: FC<{ } const constantValueProps$ = state( - lookup$.pipe( - map((lookup) => ({ lookup, builder: getDynamicBuilder(lookup) })), + dynamicBuilder$.pipe( + map((builder) => ({ + builder, + lookup: builder.lookup, + })), ), null, ) diff --git a/src/pages/Explorer/BlockPopover.tsx b/src/pages/Explorer/BlockPopover.tsx index b3d1308..9e1e939 100644 --- a/src/pages/Explorer/BlockPopover.tsx +++ b/src/pages/Explorer/BlockPopover.tsx @@ -1,7 +1,6 @@ -import { lookup$ } from "@/chain.state" +import { dynamicBuilder$ } from "@/chain.state" import { CircularProgress } from "@/components/CircularProgress" import { groupBy } from "@/lib/groupBy" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable } from "@react-rxjs/core" import { FC } from "react" import { Link } from "react-router-dom" @@ -11,14 +10,13 @@ import { BlockStatusIcon, statusText } from "./Detail/BlockState" import { filterEvt } from "./Events" const maxBlockWeight$ = state( - lookup$.pipe( - map((lookup) => { - const ct = lookup.metadata.pallets + dynamicBuilder$.pipe( + map((builder) => { + const ct = builder.lookup.metadata.pallets .find((p) => p.name === "System") ?.constants.find((ct) => ct.name === "BlockWeights") if (!ct) return null - return getDynamicBuilder(lookup).buildDefinition(ct.type).dec(ct.value) - .max_block as Weight + return builder.buildDefinition(ct.type).dec(ct.value).max_block as Weight }), ), null, diff --git a/src/pages/Explorer/BlockTable.tsx b/src/pages/Explorer/BlockTable.tsx index 3515590..19dc99d 100644 --- a/src/pages/Explorer/BlockTable.tsx +++ b/src/pages/Explorer/BlockTable.tsx @@ -1,15 +1,11 @@ +import { chainHead$ } from "@/chain.state" import { CopyText } from "@/components/Copy" import { Popover } from "@/components/Popover" import { state, useStateObservable } from "@react-rxjs/core" import { FC } from "react" import { combineLatest, debounceTime, map, switchMap } from "rxjs" import { twMerge } from "tailwind-merge" -import { - BlockInfo, - blocksByHeight$, - chainHead$, - finalized$, -} from "./block.state" +import { BlockInfo, blocksByHeight$, finalized$ } from "./block.state" import { BlockPopover } from "./BlockPopover" const best$ = chainHead$.pipeState(switchMap((chainHead) => chainHead.best$)) diff --git a/src/pages/Explorer/BlockTime.tsx b/src/pages/Explorer/BlockTime.tsx index 195c66d..14e398e 100644 --- a/src/pages/Explorer/BlockTime.tsx +++ b/src/pages/Explorer/BlockTime.tsx @@ -1,6 +1,5 @@ -import { lookup$ } from "@/chain.state" +import { chainHead$, dynamicBuilder$ } from "@/chain.state" import { CircularProgress } from "@/components/CircularProgress" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable } from "@react-rxjs/core" import { animationFrames, @@ -9,7 +8,6 @@ import { map, switchMap, } from "rxjs" -import { chainHead$ } from "./block.state" const best$ = chainHead$.pipeState(switchMap((chainHead) => chainHead.best$)) const bestBlockTime$ = best$.pipeState( @@ -22,16 +20,14 @@ const bestBlockTime$ = best$.pipeState( }), ) const targetTime$ = state( - lookup$.pipe( - map((lookup) => { - const ct = lookup.metadata.pallets + dynamicBuilder$.pipe( + map((builder) => { + const ct = builder.lookup.metadata.pallets .find((p) => p.name === "Babe") ?.constants.find((ct) => ct.name === "ExpectedBlockTime") if (!ct) return null try { - const res = getDynamicBuilder(lookup) - .buildDefinition(ct.type) - .dec(ct.value) + const res = builder.buildDefinition(ct.type).dec(ct.value) return Number(res) } catch (_) { return null diff --git a/src/pages/Explorer/Detail/BlockDetail.tsx b/src/pages/Explorer/Detail/BlockDetail.tsx index 240d3e6..dd531c6 100644 --- a/src/pages/Explorer/Detail/BlockDetail.tsx +++ b/src/pages/Explorer/Detail/BlockDetail.tsx @@ -1,9 +1,10 @@ -import { lookup$ } from "@/chain.state" +import { dynamicBuilder$ } from "@/chain.state" import { AccountIdDisplay } from "@/components/AccountIdDisplay" import { ExpandBtn } from "@/components/Expand" import { JsonDisplay } from "@/components/JsonDisplay" import { groupBy } from "@/lib/groupBy" import { SystemEvent } from "@polkadot-api/observable-client" +import * as Tabs from "@radix-ui/react-tabs" import { state, useStateObservable } from "@react-rxjs/core" import { combineKeys } from "@react-rxjs/utils" import { FC, useEffect, useRef, useState } from "react" @@ -26,10 +27,11 @@ import { } from "../block.state" import { BlockStatusIcon, statusText } from "./BlockState" import { createExtrinsicCodec, DecodedExtrinsic } from "./extrinsicDecoder" -import * as Tabs from "@radix-ui/react-tabs" const blockExtrinsics$ = state((hash: string) => { - const decoder$ = lookup$.pipe(map(createExtrinsicCodec)) + const decoder$ = dynamicBuilder$.pipe( + map((builder) => createExtrinsicCodec(builder, builder.lookup)), + ) const body$ = blockInfo$(hash).pipe( map((v) => v.body), filter((v) => !!v), diff --git a/src/pages/Explorer/Detail/extrinsicDecoder.ts b/src/pages/Explorer/Detail/extrinsicDecoder.ts index d34a94f..f4c4ebb 100644 --- a/src/pages/Explorer/Detail/extrinsicDecoder.ts +++ b/src/pages/Explorer/Detail/extrinsicDecoder.ts @@ -16,9 +16,10 @@ import { } from "@polkadot-api/substrate-bindings" import { Codec } from "polkadot-api" -export const createExtrinsicCodec = (lookup: MetadataLookup) => { - const dynamicBuilder = getDynamicBuilder(lookup) - +export const createExtrinsicCodec = ( + dynamicBuilder: ReturnType, + lookup: MetadataLookup, +) => { // https://spec.polkadot.network/id-extrinsics#id-extrinsics-body const extrinsicHeader = enhanceDecoder(u8.dec, (value) => ({ signed: (value & 0x80) > 0, diff --git a/src/pages/Explorer/Explorer.tsx b/src/pages/Explorer/Explorer.tsx index 317bdef..0a77851 100644 --- a/src/pages/Explorer/Explorer.tsx +++ b/src/pages/Explorer/Explorer.tsx @@ -1,32 +1,24 @@ import { withSubscribe } from "@/components/withSuspense" -import { blocksByHeight$ } from "./block.state" -import { BlockTable } from "./BlockTable" -import { Summary } from "./Summary" -import { Events } from "./Events" import { Route, Routes } from "react-router-dom" +import { BlockTable } from "./BlockTable" import { BlockDetail } from "./Detail" +import { Events } from "./Events" +import { Summary } from "./Summary" -const explorer$ = blocksByHeight$ - -export const Explorer = withSubscribe( - () => ( - - } /> - - -
- - -
+export const Explorer = withSubscribe(() => ( + + } /> + + +
+ +
- } - /> - - ), - { - source$: explorer$, - }, -) + + } + /> + +)) diff --git a/src/pages/Explorer/Summary.tsx b/src/pages/Explorer/Summary.tsx index dec39e6..db701ed 100644 --- a/src/pages/Explorer/Summary.tsx +++ b/src/pages/Explorer/Summary.tsx @@ -1,8 +1,8 @@ +import { chainHead$ } from "@/chain.state" import { FC, PropsWithChildren } from "react" import { map, switchMap } from "rxjs" -import { chainHead$ } from "./block.state" -import { BlockTime } from "./BlockTime" import { twMerge } from "tailwind-merge" +import { BlockTime } from "./BlockTime" const finalized$ = chainHead$.pipeState( switchMap((chainHead) => chainHead.finalized$), diff --git a/src/pages/Explorer/block.state.ts b/src/pages/Explorer/block.state.ts index 1d82bc9..0f234d0 100644 --- a/src/pages/Explorer/block.state.ts +++ b/src/pages/Explorer/block.state.ts @@ -1,4 +1,4 @@ -import { chainClient$ } from "@/chain.state" +import { chainHead$ } from "@/chain.state" import { ChainHead$, PinnedBlocks, @@ -14,7 +14,6 @@ import { concat, concatMap, filter, - finalize, forkJoin, map, mergeMap, @@ -31,15 +30,6 @@ import { withLatestFrom, } from "rxjs" -export const chainHead$ = state( - chainClient$.pipe( - switchMap(({ observableClient }) => { - const chainHead = observableClient.chainHead$() - return concat(of(chainHead), NEVER).pipe(finalize(chainHead.unfollow)) - }), - ), -) - export const finalized$ = chainHead$.pipeState( switchMap((chainHead) => chainHead.finalized$), withDefault(null), diff --git a/src/pages/Explorer/index.ts b/src/pages/Explorer/index.ts index 55d855a..222d719 100644 --- a/src/pages/Explorer/index.ts +++ b/src/pages/Explorer/index.ts @@ -1 +1,4 @@ +import { blocksByHeight$ } from "./block.state" + export * from "./Explorer" +export const explorer$ = blocksByHeight$ diff --git a/src/pages/Extrinsics/Extrinsics.tsx b/src/pages/Extrinsics/Extrinsics.tsx index fbd0bd0..03dcf13 100644 --- a/src/pages/Extrinsics/Extrinsics.tsx +++ b/src/pages/Extrinsics/Extrinsics.tsx @@ -1,29 +1,28 @@ -import { lookup$ } from "@/chain.state" +import { dynamicBuilder$ } from "@/chain.state" +import { BinaryDisplay } from "@/codec-components/LookupTypeEdit" import { ActionButton } from "@/components/ActionButton" import { ButtonGroup } from "@/components/ButtonGroup" import { withSubscribe } from "@/components/withSuspense" import { CodecComponentType, CodecComponentValue } from "@codec-components" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { Binary } from "@polkadot-api/substrate-bindings" import { state, useStateObservable } from "@react-rxjs/core" import { useState } from "react" import { map } from "rxjs" import { EditMode } from "./EditMode" import { JsonMode } from "./JsonMode" -import { BinaryDisplay } from "@/codec-components/LookupTypeEdit" const extrinsicProps$ = state( - lookup$.pipe( - map((lookup) => { + dynamicBuilder$.pipe( + map((builder) => { const codecType = - "call" in lookup.metadata.extrinsic - ? lookup.metadata.extrinsic.call + "call" in builder.lookup.metadata.extrinsic + ? builder.lookup.metadata.extrinsic.call : // TODO v14 is this one? - lookup.metadata.extrinsic.type + builder.lookup.metadata.extrinsic.type return { - metadata: lookup.metadata, + metadata: builder.lookup.metadata, codecType, - codec: getDynamicBuilder(lookup).buildDefinition(codecType), + codec: builder.buildDefinition(codecType), } }), ), diff --git a/src/pages/RuntimeCalls/RuntimeCallQuery.tsx b/src/pages/RuntimeCalls/RuntimeCallQuery.tsx index fb74c45..ff98616 100644 --- a/src/pages/RuntimeCalls/RuntimeCallQuery.tsx +++ b/src/pages/RuntimeCalls/RuntimeCallQuery.tsx @@ -1,4 +1,4 @@ -import { lookup$, unsafeApi$ } from "@/chain.state" +import { dynamicBuilder$, lookup$, unsafeApi$ } from "@/chain.state" import { InlineLookupTypeEdit, LookupTypeEdit, @@ -6,7 +6,6 @@ import { import { ActionButton } from "@/components/ActionButton" import { ExpandBtn } from "@/components/Expand" import { getTypeComplexity } from "@/utils/shape" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable, withDefault } from "@react-rxjs/core" import { createSignal } from "@react-rxjs/utils" import { Circle, Dot } from "lucide-react" @@ -35,7 +34,7 @@ export const RuntimeCallQuery: FC = () => { selectedEntry$, unsafeApi$, inputValues$, - lookup$.pipe(map(getDynamicBuilder)), + dynamicBuilder$, ]), ) const decodedValues = inputValues.map((v, i) => diff --git a/src/pages/Storage/StorageDecode.tsx b/src/pages/Storage/StorageDecode.tsx index 9376163..4911f00 100644 --- a/src/pages/Storage/StorageDecode.tsx +++ b/src/pages/Storage/StorageDecode.tsx @@ -1,7 +1,6 @@ -import { lookup$ } from "@/chain.state" +import { dynamicBuilder$ } from "@/chain.state" import { ActionButton } from "@/components/ActionButton" import { NOTIN } from "@codec-components" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable } from "@react-rxjs/core" import { createSignal } from "@react-rxjs/utils" import { FC } from "react" @@ -11,11 +10,9 @@ import { addStorageSubscription, selectedEntry$ } from "./storage.state" const [valueChange, setValue] = createSignal() const value$ = state(valueChange, "") -const valueDecoder$ = combineLatest([selectedEntry$, lookup$]).pipe( - map(([selectedEntry, lookup]) => - selectedEntry - ? getDynamicBuilder(lookup).buildDefinition(selectedEntry.value).dec - : null, +const valueDecoder$ = combineLatest([selectedEntry$, dynamicBuilder$]).pipe( + map(([selectedEntry, builder]) => + selectedEntry ? builder.buildDefinition(selectedEntry.value).dec : null, ), ) const decodedValue$ = state( diff --git a/src/pages/Storage/StorageQuery.tsx b/src/pages/Storage/StorageQuery.tsx index 28fc5ec..3c873ae 100644 --- a/src/pages/Storage/StorageQuery.tsx +++ b/src/pages/Storage/StorageQuery.tsx @@ -1,4 +1,4 @@ -import { lookup$, unsafeApi$ } from "@/chain.state" +import { dynamicBuilder$, unsafeApi$ } from "@/chain.state" import { EditCodec } from "@/codec-components/EditCodec" import { ActionButton } from "@/components/ActionButton" import { BinaryEditButton } from "@/components/BinaryEditButton" @@ -9,7 +9,6 @@ import { CodecComponentValue, NOTIN, } from "@codec-components" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable, withDefault } from "@react-rxjs/core" import { createSignal } from "@react-rxjs/utils" import { Binary } from "polkadot-api" @@ -149,7 +148,7 @@ const StorageKeysInput: FC = () => { ) } -const lookupState$ = state(lookup$, null) +const builderState$ = state(dynamicBuilder$, null) const keyInputValue$ = state( (idx: number) => keyValues$.pipe( @@ -182,12 +181,12 @@ const StorageKeyInput: FC<{ idx: number; type: number; disabled: boolean }> = ({ type, disabled, }) => { - const lookup = useStateObservable(lookupState$) + const builder = useStateObservable(builderState$) const value = useStateObservable(keyInputValue$(idx)) - if (!lookup) return null + if (!builder) return null - const codec = getDynamicBuilder(lookup).buildDefinition(type) + const codec = builder.buildDefinition(type) const binaryValue = (value.type === CodecComponentType.Initial ? value.value @@ -196,7 +195,7 @@ const StorageKeyInput: FC<{ idx: number; type: number; disabled: boolean }> = ({ : (value.value.encoded ?? codec.enc(value.value.decoded))) ?? null const getTypeName = () => { - const lookupEntry = lookup(type) + const lookupEntry = builder.lookup(type) switch (lookupEntry.type) { case "primitive": return lookupEntry.value @@ -241,7 +240,7 @@ const StorageKeyInput: FC<{ idx: number; type: number; disabled: boolean }> = ({ /> @@ -253,8 +252,13 @@ const StorageKeyInput: FC<{ idx: number; type: number; disabled: boolean }> = ({ } const encodedKey$ = state( - combineLatest([lookup$, selectedEntry$, keyValues$, keysEnabled$]).pipe( - map(([lookup, selectedEntry, keyValues, keysEnabled]) => { + combineLatest([ + dynamicBuilder$, + selectedEntry$, + keyValues$, + keysEnabled$, + ]).pipe( + map(([builder, selectedEntry, keyValues, keysEnabled]) => { const args = keyValues.slice(0, keysEnabled) if ( keyValues.length < keysEnabled || @@ -264,7 +268,7 @@ const encodedKey$ = state( return null } - const codec = getDynamicBuilder(lookup).buildStorage( + const codec = builder.buildStorage( selectedEntry.pallet, selectedEntry.entry, ) @@ -279,17 +283,14 @@ const encodedKey$ = state( ) const KeyDisplay: FC = () => { const key = useStateObservable(encodedKey$) - const lookup = useStateObservable(lookupState$) + const builder = useStateObservable(builderState$) const selectedEntry = useStateObservable(selectedEntry$) const keys = useStateObservable(keys$) const keysEnabled = useStateObservable(keysEnabled$) - if (!lookup || !selectedEntry) return null + if (!builder || !selectedEntry) return null - const codec = getDynamicBuilder(lookup).buildStorage( - selectedEntry.pallet, - selectedEntry.entry, - ) + const codec = builder.buildStorage(selectedEntry.pallet, selectedEntry.entry) return (
diff --git a/src/pages/Storage/StorageSubscriptions.tsx b/src/pages/Storage/StorageSubscriptions.tsx index 80c3ba8..94b7d0c 100644 --- a/src/pages/Storage/StorageSubscriptions.tsx +++ b/src/pages/Storage/StorageSubscriptions.tsx @@ -1,15 +1,13 @@ -import { lookup$, metadata$ } from "@/chain.state" +import { dynamicBuilder$, metadata$ } from "@/chain.state" import { ViewCodec } from "@/codec-components/ViewCodec" import { CopyBinary } from "@/codec-components/ViewCodec/CopyBinary" import { ButtonGroup } from "@/components/ButtonGroup" import { JsonDisplay } from "@/components/JsonDisplay" import { CodecComponentType, NOTIN } from "@codec-components" -import { getDynamicBuilder } from "@polkadot-api/metadata-builders" import { state, useStateObservable } from "@react-rxjs/core" import { PauseCircle, PlayCircle, Trash2 } from "lucide-react" import { FC, useMemo, useState } from "react" import { Virtuoso } from "react-virtuoso" -import { map } from "rxjs" import { removeStorageSubscription, StorageSubscription, @@ -154,10 +152,7 @@ const itemClasses = "py-2 border-b first:pt-0 last:pb-0 last:border-b-0" const VirtuosoItem: FC = (props) =>
const metadataState$ = state(metadata$, null) -const dynamicBuilder$ = state( - lookup$.pipe(map((v) => getDynamicBuilder(v))), - null, -) +const dynamicBuilderState$ = state(dynamicBuilder$, null) export const ValueDisplay: FC<{ type: number title: string @@ -165,7 +160,7 @@ export const ValueDisplay: FC<{ mode: "decoded" | "json" }> = ({ type, title, value, mode }) => { const metadata = useStateObservable(metadataState$) - const builder = useStateObservable(dynamicBuilder$) + const builder = useStateObservable(dynamicBuilderState$) const [codec, encodedValue] = useMemo(() => { if (!builder) return [null!, null!]