fix: remove the fork-with options, and name the workflow step for what it does
All checks were successful
deploy / build (push) Successful in 5m11s
deploy / deploy-web (push) Successful in 6s

**Fork with Chopsticks / Forklift is gone.** Neither can fork a chain in this
list. Chopsticks is built on `@polkadot/types`, which cannot decode a Quantus
block at all — it caps fixed arrays at 2048 bytes where ML-DSA signatures are
5261 and 7219, reads the extrinsic preamble byte as a version, and knows nothing
of this chain's header layout. Forklift resolves its own unpatched copy of
`@polkadot-api/substrate-bindings`, so it hits the very header bug this console
patches around.

So the two buttons offered things that could only fail, and fail without saying
why. Removed rather than disabled: a greyed-out control still asks the reader to
work out why. `forkMethod` stays in SelectedChain because the hash params and
chain.state still read it; nothing in the UI can now set it to anything but
"none", so the two light-client guards that reset it go with it.

**The workflow step called "the patch is applied"** — an assertion sitting in a
list of imperatives (install, build, ship the bundle), reading like a claim CI
was making rather than a thing it was doing. Now "verify the signers-common
patch".

Verified in a browser: the switcher shows Quantus, Heisenberg, Planck and
Localhost with both endpoints per chain and no FORK WITH row, and the explorer
still runs — Finalized 54,153, Best 54,253.

Refs #3

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
This commit is contained in:
2026-09-16 10:16:48 +03:00
parent 6358367b61
commit 2c8cefab07
2 changed files with 16 additions and 62 deletions

View File

@@ -58,7 +58,7 @@ jobs:
# shipping a console that rejects every Quantus signature at run time.
run: pnpm install --frozen-lockfile
- name: the patch is applied
- name: verify the signers-common patch
# Cheap, and it is the one thing about this fork that a normal build
# would not notice going missing. Without it every signing attempt dies
# with `Unkown signer` — in the browser, after deploy, to a user.

View File

@@ -1,7 +1,5 @@
import { CopyText } from "@/components/Copy"
import {
Chopsticks,
Forklift,
ForkMethodIcon,
Spinner,
} from "@/components/Icons"
@@ -28,7 +26,6 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import {
AUTO_RPC_ENDPOINT,
currentWsStatus$,
ForkMethod,
LIGHT_CLIENT_ENDPOINT,
Network,
networkCategories,
@@ -85,10 +82,21 @@ const NetworkSwitchDialogContent: FC<{
const [query, setQuery] = useState("")
const [network, setNetwork] = useState(selectedChain.network)
const [endpoint, setEndpoint] = useState(selectedChain.endpoint)
const [forkMethod, setForkMethod] = useState(selectedChain.forkMethod)
const customUrl = normalizeWsUrl(query)
const canFork = endpoint !== LIGHT_CLIENT_ENDPOINT
const selectedForkMethod = canFork ? forkMethod : "none"
// Forking is not offered.
//
// Chopsticks is built on `@polkadot/types`, which cannot decode a Quantus
// block at all: it caps fixed arrays at 2048 bytes where ML-DSA signatures are
// 5261 and 7219, reads the extrinsic preamble byte as a version, and knows
// nothing of this chain's header layout. Forklift resolves its own unpatched
// copy of `@polkadot-api/substrate-bindings`, so it hits the very header bug
// this console patches around.
//
// Neither can fork a chain in this list, so the two buttons offered things
// that could only fail, and fail without saying why. `forkMethod` stays in
// SelectedChain — the hash params and chain.state still read it — but nothing
// in the UI can now set it to anything other than "none".
const selectedForkMethod = "none" as const
const hasChanged =
network.id !== selectedChain.network.id ||
endpoint !== selectedChain.endpoint ||
@@ -100,9 +108,6 @@ const NetworkSwitchDialogContent: FC<{
) => {
setNetwork(next)
setEndpoint(nextEndpoint)
if (nextEndpoint === LIGHT_CLIENT_ENDPOINT) {
setForkMethod("none")
}
}
const selectCustomUrl = (url: string) => {
@@ -112,14 +117,8 @@ const NetworkSwitchDialogContent: FC<{
const setConnection = (nextEndpoint: string) => {
setEndpoint(nextEndpoint)
if (nextEndpoint === LIGHT_CLIENT_ENDPOINT) {
setForkMethod("none")
}
}
const toggleForkMethod = (method: ForkMethod) => {
setForkMethod((current) => (current === method ? "none" : method))
}
const confirm = () => {
if (network.id === "custom") {
@@ -185,32 +184,7 @@ const NetworkSwitchDialogContent: FC<{
/>
</div>
<div className="flex shrink-0 items-center justify-between gap-3 border-t pt-3">
{canFork ? (
<div className="flex min-w-0 items-center gap-3">
<div className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
Fork with
</div>
<div className="flex flex-wrap gap-2">
<ForkMethodOption
value="chopsticks"
title="Chopsticks"
selected={selectedForkMethod === "chopsticks"}
icon={<Chopsticks size={18} />}
onSelect={toggleForkMethod}
/>
<ForkMethodOption
value="forklift"
title="Forklift"
selected={selectedForkMethod === "forklift"}
icon={<Forklift size={18} />}
onSelect={toggleForkMethod}
/>
</div>
</div>
) : (
<div />
)}
<div className="flex shrink-0 items-center justify-end gap-3 border-t pt-3">
<Button
className="min-w-28"
onClick={confirm}
@@ -227,26 +201,6 @@ const NetworkSwitchDialogContent: FC<{
)
}
const ForkMethodOption: FC<{
value: Exclude<ForkMethod, "none">
title: string
selected: boolean
icon?: React.ReactNode
onSelect: (value: ForkMethod) => void
}> = ({ value, title, selected, icon, onSelect }) => (
<button
type="button"
className={twMerge(
"flex items-center gap-1.5 rounded-md border border-transparent px-2 py-1.5 text-sm",
selected && "border-polkadot bg-polkadot/5",
)}
aria-pressed={selected}
onClick={() => onSelect(value)}
>
{icon}
{title}
</button>
)
const NetworkList: FC<{
query: string