Skip to content

feat(ui): action-sentence layer for extrinsic/event headlines - #8453

Merged
JSONbored merged 1 commit into
mainfrom
feat/action-sentences
Jul 27, 2026
Merged

feat(ui): action-sentence layer for extrinsic/event headlines#8453
JSONbored merged 1 commit into
mainfrom
feat/action-sentences

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #8371 — client-side UI deliverable. Scope note posted on the issue before implementation: the schema/API summary contract field is deferred to a follow-up rather than bundled into this PR (see the issue comment for the full reasoning).

What this does

New apps/ui/src/lib/metagraphed/chain-summaries.ts: summarizeCall()/summarizeEvent() render a one-line action sentence over the existing decode infrastructure (#4319 nested-call decode, #8322 decoded events) — the issue's own worked example, "Validator 5GQi…sQQ committed time-locked weights for SN89, revealing at round 30,777,610", instead of SubtensorModule.commit_timelocked_mechanism_weights plus a raw arg table. A pallet.method with no template returns null; callers keep today's raw rendering — a sentence is never guessed.

Grounded in real data, not assumption

  • Pulled the top-40 call/event combinations by real observed volume from GET /api/v1/chain/calls?group_by=module_function and GET /api/v1/chain-events/stats — the top 20 calls alone cover ~97% of volume, so every template targets something that actually matters.
  • Every template was checked against a real decoded payload fetched live from api.metagraph.sh before being written, not guessed.
  • Found and worked around a real arg-shape surprise along the way: chain_events payloads are frequently positional arrays with no field names at all — confirmed live for WeightsSet ([[89], 122]), StakeAdded/StakeRemoved ([coldkey, hotkey, [amount], [amount2], [netuid], version]), NeuronRegistered ([[netuid], uid, hotkey]), and both TimelockedWeights* events — distinct from account_events's keyed-object shape, and the field order differs per event. My first coverage run (94.68%, just under the 95% bar) caught this directly: templates that assumed named fields were silently returning null on these five high-volume events. Fixed by reading positional args by index against the real captured shape for each.
  • Also found RootClaimed carries no netuid field at all (just {coldkey}), and AutoStakeAdded's amount field is named incentive, not amount — both fixed to match reality rather than the assumed shape.

Wired into three surfaces

  • Extrinsic detail masthead: sentence as the headline; raw module.function demotes to the existing "Call" field row further down (unchanged).
  • Raw all-events feed (ChainEventCard + the desktop table in chain-events-feed.tsx): leads with the sentence, falling back to Pallet.Method when there's no template. This is shared by /events, the embedded Chain-hub preview, and anywhere else the component is reused.
  • Account detail's "Signed extrinsics" section: same sentence, with the account itself as the signer context (it's filtered to extrinsics that account signed).

Coverage: 98.37%, past the 95% bar

chain-summaries.coverage.test.ts — opt-in (RUN_COVERAGE=1 npx vitest run src/lib/metagraphed/chain-summaries.coverage.test.ts), describe.skipIf-gated so it's a no-op in normal CI (no network dependency there). Measured against the most recent ~10k extrinsics + ~10k chain events from production:

Extrinsics: 9722/10000 (97.22%)
Chain events: 9952/10000 (99.52%)
Combined: 19674/20000 (98.37%)

Remaining extrinsic gaps are long-tail calls under ~1% volume each (remove_stake_full_limit, serve_axon, burned_register, transfer_stake, etc.) — deliberately left as null-returning gaps rather than guessed, since I don't have verified real arg shapes for them in this session.

Verification

New tests: 52 cases in chain-summaries.test.ts (one fixture per template family, using the real captured shapes above — including the positional-array cases and both the "found via a template with wrong assumptions" fixes). tsc --noEmit and scoped eslint clean. Full suite: 1626 passed, 1 skipped (the opt-in coverage test) across 206 files.

Verified live via a local dev server against real production data:

  • An extrinsic detail page for a real Balances.transfer_keep_alive renders "5FqBL9…Lxoy2s transferred 1.00 τ to 5DxQZ2…7uodow." as the headline, with the raw Balances.transfer_keep_alive still present in the Call field row below.
  • /events now reads as a stream of real sentences — "committed time-locked weights, revealing at round X", "Weights were set for SN128", "Transferred X from A to B" — instead of a wall of Pallet.Method labels.
  • A real account's "Signed extrinsics" section renders the same sentences per row.

Maintainer PR — reviewed live via a local dev server rather than the contributor screenshot matrix (existing card/table/masthead chrome is unchanged; only the text content inside changes).

Closes #8371 (client-side UI deliverable; the schema/API contract
field is scoped out -- see PR description)

New apps/ui/src/lib/metagraphed/chain-summaries.ts: summarizeCall()/
summarizeEvent() render a one-line action sentence over the existing
decode infrastructure (#4319/#8322) -- "5GQi...sQQ committed
time-locked weights for SN89, revealing at round 30,777,610" instead
of "SubtensorModule.commit_timelocked_mechanism_weights" plus a raw
arg table. A pallet.method with no template returns null; callers
keep today's raw rendering rather than ever guessing a sentence.

Every template is grounded in a real decoded payload captured live
from api.metagraph.sh, including several arg-shape surprises found
along the way: chain_events args are frequently POSITIONAL arrays
(no field names at all) rather than the keyed objects account_events
uses, and the exact positions differ per pallet.method -- confirmed
individually for WeightsSet, StakeAdded/Removed, NeuronRegistered,
and both TimelockedWeights* events before writing their templates.

Wired into three surfaces: the extrinsic detail masthead (sentence
as headline, raw module.function demoted to the existing "Call"
field row), the raw all-events feed (ChainEventCard + desktop table),
and an account's own "Signed extrinsics" section.

Coverage measured against the most recent 10k extrinsics + 10k chain
events from production (chain-summaries.coverage.test.ts, opt-in via
RUN_COVERAGE=1, skipped in normal CI): 98.37% combined (97.22%
extrinsics, 99.52% events) -- comfortably past the issue's 95% bar.
@loopover-orb

loopover-orb Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Important

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏳ LoopOver is waiting…

LoopOver has seen this pull request and is waiting on CI checks to finish before reviewing it. This comment will update once the review runs.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed · 🟨 Waiting

@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
metagraphed-ui f2548cf Commit Preview URL

Branch Preview URL
Jul 27 2026, 06:15 PM

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.81%. Comparing base (3ad9a81) to head (f2548cf).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8453   +/-   ##
=======================================
  Coverage   97.81%   97.81%           
=======================================
  Files         419      419           
  Lines       29074    29074           
  Branches    10931    10931           
=======================================
  Hits        28440    28440           
  Misses        143      143           
  Partials      491      491           
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit 3e59b32 into main Jul 27, 2026
11 checks passed
@JSONbored
JSONbored deleted the feat/action-sentences branch July 27, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(api+ui): action sentences — a human-readable summary field on every extrinsic and event

1 participant