Files
observer/web/src/api/generated/BlockDetail.ts
rob thijssen 88086552cb
All checks were successful
deploy / build (push) Successful in 9m18s
deploy / deploy-web (push) Successful in 4s
deploy / deploy-api (push) Successful in 14s
fix: show a block's events, joined to the extrinsics that caused them
The block page listed extrinsics and nothing else. Block 1 holds twenty-eight
indexed events and the route returned none of them — visible from the outside,
because an account page linked to a `Wormhole::NativeTransferred` at block 1 and
block 1 showed no sign of it.

`phase` and `extrinsic_index` were stored for exactly this join and had never
been used. Each extrinsic now carries its own events beneath it, and the block's
own events sit in their phases.

Block 1 is the argument for doing it that way. As extrinsics alone it is a
single `Timestamp::set`. Its events are the entire opening distribution:
twenty-one `Wormhole::NativeTransferred` in `Initialization`, owned by no
extrinsic at all and sent from the minting account — not block zero, and not
anything a transaction did. `Vesting::LaunchMomentSet` fires there too, so
vesting has been exercised despite the call index showing zero `Vesting::*`
dispatched: a pallet the runtime uses looks unused from the call side alone.

Closes #3

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
2026-09-10 09:14:56 +03:00

135 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AttributionSource } from "./AttributionSource";
import type { BigUintDec } from "./BigUintDec";
import type { BlockEvent } from "./BlockEvent";
import type { BlockExtrinsic } from "./BlockExtrinsic";
import type { ChainId } from "./ChainId";
import type { MinerId } from "./MinerId";
/**
* One block, as completely as it can still be described.
*
* Assembled from two sources that know different things, because neither is
* sufficient on its own:
*
* - The **node** holds the block itself — parent, body, and whether this hash
* still holds its height. It forgets: `blocks-pruning` defaults to
* `archive-canonical`, so a non-canonical body goes once finality passes it,
* and difficulty is a state read behind a 256-block window.
* - The **observer** holds what the node never had — when we first saw the
* block, whether that sighting was at the tip — and what it has since
* forgotten, the difficulty recorded while the state still existed.
*
* Every field the pair cannot supply is `None` rather than a substituted
* plausible value. A block page that quietly filled in the current difficulty
* for one it could not look up would be the same lie the ingest path was fixed
* to stop telling.
*/
export type BlockDetail = {
/**
* Which chain.
*/
chain: ChainId,
/**
* Block number.
*/
height: number,
/**
* This block's hash — the identity the page is addressed by, so that a
* link keeps meaning the same block after the height has moved on.
*/
hash: string,
/**
* Parent hash, from the header.
*/
parent_hash: string | null,
/**
* Author's reward preimage from the `pow_` PreRuntime digest.
*/
miner: MinerId | null,
/**
* What to call the author: a telemetry node name, or the abbreviated
* preimage. `None` where the author could not be decoded at all.
*/
display: string | null,
/**
* Whether `display` is an inferred name or the preimage.
*/
attribution: AttributionSource | null,
/**
* How much of the attribution vote window agrees, 0.01.0.
*/
confidence: number | null,
/**
* Expected hashes to win this block: the difficulty in force at its
* parent, which is the figure the miner actually had to meet.
*/
difficulty: BigUintDec | null,
/**
* The author's own timestamp, from the block's `Timestamp::set` inherent.
*/
authored_at: string | null,
/**
* When this observer first saw the block. `None` for a block it never saw
* at all — an orphan on a fork it missed, or history before it started.
*/
observed_at: string | null,
/**
* Whether `observed_at` was a tip sighting. When false, the difference
* between the timestamps measures when the observer got round to looking
* and nothing about the network, so the UI must not read it as propagation.
*/
at_tip: boolean | null,
/**
* Seconds between this block's timestamp and its parent's — how long this
* block took to find, against the chain's target.
*/
seconds_since_parent: number | null,
/**
* Extrinsics in the body, inherents included. `None` once the body has
* been pruned.
*/
extrinsics: number | null,
/**
* The block's events, in the order they fired.
*
* Grouped by a reader rather than here: `phase` says whether an event
* belongs to an extrinsic or to the block itself, and `extrinsic_index`
* says which extrinsic. A block's opening distribution can arrive entirely
* in `Initialization`, owned by no extrinsic at all — which is exactly
* what block 1 on this chain does, and what a page showing only extrinsics
* misses.
*/
events: Array<BlockEvent>,
/**
* The extrinsics themselves, decoded, in body order.
*
* From this observer's index rather than from the node, which is why they
* survive the node forgetting the block: the count above comes from the
* body and goes with it, these do not. Empty for a block the index has not
* reached — the backfill works outward from the tip — which is a different
* thing from a block with no extrinsics, and the page says so.
*/
body: Array<BlockExtrinsic>,
/**
* Whether this hash is the one that currently holds this height.
*/
canonical: boolean,
/**
* The hash that currently holds this height. Equal to `hash` when
* canonical; on an orphan page it is the link to the block that won.
*/
canonical_hash: string | null,
/**
* Other hashes this observer has recorded at this height — the losing
* sides of past reorgs. Navigable, which is the whole reason the
* displacement is written down.
*/
also_seen: Array<string>,
/**
* False when the node could not be reached or no longer holds the block,
* so everything here came from what the observer had already recorded.
* The UI owes the reader that distinction rather than showing gaps.
*/
from_node: boolean, };