add pallets inspector
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
||||
} from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
export const Lookup: FC<{ lookup: V14Lookup }> = ({ lookup }) => {
|
||||
export const Lookup: FC = () => {
|
||||
const [id, setId] = useState(0)
|
||||
|
||||
return (
|
||||
@@ -26,9 +26,7 @@ export const Lookup: FC<{ lookup: V14Lookup }> = ({ lookup }) => {
|
||||
/>
|
||||
</label>
|
||||
<div className="border-t max-h-[75vh] overflow-auto">
|
||||
<LookupContext.Provider value={lookup}>
|
||||
<LookupNode id={id} />
|
||||
</LookupContext.Provider>
|
||||
<LookupNode id={id} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -42,7 +40,7 @@ type NodeProps<T extends V14Def["tag"]> = {
|
||||
value: V14SpecificDef<T>
|
||||
}
|
||||
|
||||
const LookupContext = createContext<V14Lookup>(null as any)
|
||||
export const LookupContext = createContext<V14Lookup>(null as any)
|
||||
|
||||
const LookupNode: FC<{ id: number }> = ({ id }) => {
|
||||
const lookup = useContext(LookupContext)
|
||||
@@ -69,7 +67,7 @@ const LookupNode: FC<{ id: number }> = ({ id }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const LookupLink: FC<{ id: number }> = ({ id }) => {
|
||||
export const LookupLink: FC<{ id: number }> = ({ id }) => {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,8 @@ import { V14, V15 } from "@polkadot-api/substrate-bindings"
|
||||
import { useStateObservable } from "@react-rxjs/core"
|
||||
import { FC, useState } from "react"
|
||||
import { Route, Routes, useParams } from "react-router-dom"
|
||||
import { Lookup } from "./Lookup"
|
||||
import { Lookup, LookupContext } from "./Lookup"
|
||||
import { Pallets } from "./Pallets"
|
||||
|
||||
export const Metadata = withSubscribe(
|
||||
() => (
|
||||
@@ -54,8 +55,11 @@ const MetadataExplorer = () => {
|
||||
|
||||
const DecodedExplorer: FC<{ value: V14 | V15 }> = ({ value }) => {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<Lookup lookup={value.lookup} />
|
||||
<div className="w-full flex flex-col gap-2">
|
||||
<LookupContext.Provider value={value.lookup}>
|
||||
<Lookup />
|
||||
<Pallets pallets={value.pallets} />
|
||||
</LookupContext.Provider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
import { SearchableSelect } from "@/components/Select"
|
||||
import { V14, V15 } from "@polkadot-api/substrate-bindings"
|
||||
import { FC, useEffect, useState } from "react"
|
||||
import { LookupLink } from "./Lookup"
|
||||
import { CopyText } from "@/components/Copy"
|
||||
|
||||
type Pallet = (V14 | V15)["pallets"][number]
|
||||
export const Pallets: FC<{ pallets: Array<Pallet> }> = ({ pallets }) => {
|
||||
const [pallet, setPallet] = useState<Pallet | null>(null)
|
||||
|
||||
return (
|
||||
<div className="border rounded p-2 flex flex-col gap-2">
|
||||
<h3 className="font-bold text-xl">Pallets</h3>
|
||||
<label className="self-start">
|
||||
Pallet:{" "}
|
||||
<SearchableSelect
|
||||
value={pallet}
|
||||
setValue={setPallet}
|
||||
options={pallets.map((p) => ({
|
||||
text: p.name,
|
||||
value: p,
|
||||
}))}
|
||||
/>
|
||||
</label>
|
||||
{pallet && (
|
||||
<>
|
||||
<p>Index: {pallet.index}</p>
|
||||
{pallet.storage && (
|
||||
<div>
|
||||
<h4>Storage</h4>
|
||||
<PalletStorage pallet={pallet} />
|
||||
</div>
|
||||
)}
|
||||
{pallet.constants.length && (
|
||||
<div>
|
||||
<h4>Constants</h4>
|
||||
<PalletConstants pallet={pallet} />
|
||||
</div>
|
||||
)}
|
||||
{pallet.calls != null && (
|
||||
<div>
|
||||
<h4>Calls</h4>
|
||||
<LookupLink id={pallet.calls} />
|
||||
</div>
|
||||
)}
|
||||
{pallet.events != null && (
|
||||
<div>
|
||||
<h4>Events</h4>
|
||||
<LookupLink id={pallet.events} />
|
||||
</div>
|
||||
)}
|
||||
{pallet.errors != null && (
|
||||
<div>
|
||||
<h4>Errors</h4>
|
||||
<LookupLink id={pallet.errors} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type StorageEntry = Pallet["storage"] extends
|
||||
| undefined
|
||||
| { items: Array<infer R> }
|
||||
? R
|
||||
: never
|
||||
const PalletStorage: FC<{ pallet: Pallet }> = ({ pallet }) => {
|
||||
const [entry, setEntry] = useState<StorageEntry | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setEntry(null)
|
||||
}, [pallet])
|
||||
|
||||
if (!pallet.storage) return null
|
||||
|
||||
const value =
|
||||
entry &&
|
||||
(entry.type.tag === "map" ? entry.type.value.value : entry.type.value)
|
||||
const key = entry && (entry.type.tag === "map" ? entry.type.value.key : null)
|
||||
const acceptsPartialKey =
|
||||
entry?.type.tag === "map" && entry.type.value.hashers.length > 1
|
||||
|
||||
return (
|
||||
<div className="flex flex-col p-2 gap-2">
|
||||
<label className="self-start">
|
||||
Entry:{" "}
|
||||
<SearchableSelect
|
||||
value={entry}
|
||||
setValue={setEntry}
|
||||
options={pallet.storage.items.map((s) => ({
|
||||
text: s.name,
|
||||
value: s,
|
||||
}))}
|
||||
/>
|
||||
</label>
|
||||
{entry && (
|
||||
<>
|
||||
{key != null && (
|
||||
<div>
|
||||
<h4>Key</h4>
|
||||
{acceptsPartialKey && <p>Accepts partial keys</p>}
|
||||
<LookupLink id={key} />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<h4>Value</h4>
|
||||
<LookupLink id={value!} />
|
||||
</div>
|
||||
<div>
|
||||
<h4>Fallback</h4>
|
||||
<div className="whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
<CopyText text={entry.fallback} binary className="mr-2" />
|
||||
{entry.fallback}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type ConstantEntry = Pallet["constants"] extends Array<infer R> ? R : never
|
||||
const PalletConstants: FC<{ pallet: Pallet }> = ({ pallet }) => {
|
||||
const [entry, setEntry] = useState<ConstantEntry | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setEntry(null)
|
||||
}, [pallet])
|
||||
|
||||
if (!pallet.constants.length) return null
|
||||
|
||||
return (
|
||||
<div className="flex flex-col p-2 gap-2">
|
||||
<label className="self-start">
|
||||
Entry:{" "}
|
||||
<SearchableSelect
|
||||
value={entry}
|
||||
setValue={setEntry}
|
||||
options={pallet.constants.map((c) => ({
|
||||
text: c.name,
|
||||
value: c,
|
||||
}))}
|
||||
/>
|
||||
</label>
|
||||
{entry && (
|
||||
<>
|
||||
<div>
|
||||
<h4>Type</h4>
|
||||
<LookupLink id={entry.type} />
|
||||
</div>
|
||||
<div>
|
||||
<h4>Value</h4>
|
||||
<div className="whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
<CopyText text={entry.value} binary className="mr-2" />
|
||||
{entry.value}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user