allow loading blocks from previous runtimes (#85)

This commit is contained in:
Josep M Sobrepere
2025-09-21 11:59:52 +02:00
committed by GitHub
parent ec18347c97
commit c0801f206f
2 changed files with 50 additions and 22 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
import { Chopsticks } from "@/components/Icons"
import { Loading } from "@/components/Loading"
import { groupBy } from "@/lib/groupBy"
import { runtimeCtx$ } from "@/state/chains/chain.state"
import { runtimeCtxAt$ } from "@/state/chains/chain.state"
import * as Tabs from "@radix-ui/react-tabs"
import { state, useStateObservable } from "@react-rxjs/core"
import { FC, useState } from "react"
@@ -24,7 +24,7 @@ const blockExtrinsics$ = state((hash: string) => {
distinctUntilChanged(),
)
return combineLatest([body$, runtimeCtx$]).pipe(
return combineLatest([body$, runtimeCtxAt$(hash)]).pipe(
take(1),
map(([body, { txDecoder }]) =>
body.map((raw, idx) => ({
+48 -20
View File
@@ -25,10 +25,13 @@ import {
firstValueFrom,
from,
map,
mergeMap,
NEVER,
Observable,
of,
startWith,
switchMap,
take,
} from "rxjs"
import {
addCustomNetwork,
@@ -148,13 +151,16 @@ const selectedSource$ = selectedChain$.pipe(switchMap(getChainSource))
// remove old localStorage clear after a while
localStorage.removeItem("metadata-cache")
type MetadataCache = Map<string, { id: string; time: number; data: HexString }>
type MetadataCache = Map<
string,
{ id: string; time: number; data: HexString; codeHash: HexString }
>
const IDB_KEY = "metadata-cache"
const MAX_CACHE_ENTRIES = 3
const addEntryToCache = (
codeHash: string,
entry: { id: string; time: number; data: HexString },
entry: { id: string; time: number; data: HexString; codeHash: HexString },
) =>
update<MetadataCache>(IDB_KEY, (cached) => {
cached ??= new Map()
@@ -191,7 +197,12 @@ const getMetadata = (codeHash: string | null) =>
const setMetadataFactory =
(id: string) => (codeHash: string | null, data: Uint8Array) => {
if (codeHash)
addEntryToCache(codeHash, { id, time: Date.now(), data: toHex(data) })
addEntryToCache(codeHash, {
id,
time: Date.now(),
data: toHex(data),
codeHash,
})
}
export const chainClient$ = state(
@@ -249,6 +260,28 @@ const uncachedRuntimeCtx$ = chainClient$.pipeState(
filter(Boolean),
)
const withTxDecoder: <T extends { metadataRaw: Uint8Array }>(
input: Observable<T>,
) => Observable<T & { txDecoder: ReturnType<typeof getExtrinsicDecoder> }> =
map((ctx) => ({
...ctx,
txDecoder: getExtrinsicDecoder(ctx.metadataRaw),
}))
export const runtimeCtxAt$ = state((atBlock: string) =>
chainClient$.pipe(
take(1),
mergeMap((client) => {
const pinned = client.chainHead.pinnedBlocks$.state
return (
pinned.runtimes[pinned.blocks.get(atBlock)?.runtime!]?.runtime ||
client.chainHead.getRuntimeContext$(atBlock)
)
}),
withTxDecoder,
),
)
export const runtimeCtx$ = chainClient$.pipeState(
switchMap(({ id }) =>
get<MetadataCache>(IDB_KEY).then((cache) =>
@@ -256,25 +289,20 @@ export const runtimeCtx$ = chainClient$.pipeState(
),
),
switchMap((cached) => {
if (cached) {
const metadata = unifyMetadata(decAnyMetadata(cached[1].data))
const lookup = getLookupFn(metadata)
const dynamicBuilder = getDynamicBuilder(lookup)
if (!cached) return uncachedRuntimeCtx$
const metadata = unifyMetadata(decAnyMetadata(cached[1].data))
const lookup = getLookupFn(metadata)
const dynamicBuilder = getDynamicBuilder(lookup)
return uncachedRuntimeCtx$.pipe(
startWith({
metadataRaw: fromHex(cached[1].data),
lookup,
dynamicBuilder,
}),
)
}
return uncachedRuntimeCtx$
return uncachedRuntimeCtx$.pipe(
startWith({
metadataRaw: fromHex(cached[1].data),
lookup,
dynamicBuilder,
}),
)
}),
map((ctx) => ({
...ctx,
txDecoder: getExtrinsicDecoder(ctx.metadataRaw),
})),
withTxDecoder,
)
export const lookup$ = runtimeCtx$.pipeState(map((ctx) => ctx.lookup))