You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AccountDetail in apps/ui/src/routes/accounts.$ss58.tsx renders three data tables via AccountEventsSection (Chain events, #events, line 624), AccountExtrinsicsSection (Signed extrinsics, #extrinsics, line 356), and AccountTransfersSection (Transfers, #transfers, line 432) — none of which offer an export affordance. All three backing routes already accept ?format=csv per src/contracts.mjs: GET /api/v1/accounts/{ss58}/events (line 2416), GET /api/v1/accounts/{ss58}/extrinsics (line 2452), and GET /api/v1/accounts/{ss58}/transfers (line 2469), each wrapped in csvRouteQuery(...). No CSV/download UI exists anywhere in apps/ui/src today — this is the first page to wire it up.
Requirement
Add a "Download CSV" affordance to each of the three tabs (SectionAnchor headers for #events, #extrinsics, #transfers) that links to its own backend route with format=csv appended (and, for Events, the current ?kind= filter preserved), so a visitor can export exactly what the table currently shows.
Deliverable
File to change: apps/ui/src/routes/accounts.$ss58.tsx — add the affordance to the right={...} slot of the SectionAnchor in AccountExtrinsicsSection (currently only a row-count SectionBadge, line ~364), AccountTransfersSection (line ~440), and inside AccountEventsSection's right={...} slot alongside the existing SelectFilter for kind (lines 672-681).
URL construction: reuse buildUrl (exported from apps/ui/src/lib/metagraphed/client.ts) to build each download href — it already folds in getApiBase() (runtime-configurable API origin) and applyNetworkPrefix() (mainnet/testnet partitioning) and serializes query params, which is exactly what a correct CSV link needs. Do not hardcode API_BASE/origin directly (that snapshot pattern in endpoint-snippet.tsx skips the network prefix and is not the correct precedent here) or hand-build a query string, since that would reintroduce the href-taint-barrier class of bug this codebase already guards against in config.ts's sanitizeApiBase.
Events: buildUrl("/api/v1/accounts/{ss58}/events", { format: "csv", kind: search.ev_kind }) — must reflect the currently-applied ev_kind filter (from Route.useSearch(), already in scope in AccountEventsSection) so the export matches what's on screen; omit kind when no filter is active.
"Done" is: each of the three sections renders one DownloadCsvButton (or whatever FE: add a reusable DownloadCsvButton component (no page wiring) #3402 names it) pointed at the section's own CSV URL, positioned in the section header's right slot; clicking it downloads/opens text/csv for that tab's current rows (events respecting the active kind filter); no change to the JSON data-fetching (accountExtrinsicsQuery/accountTransfersQuery/accountEventsQuery) paths.
Acceptance criteria
apps/ui/src/routes/accounts.$ss58.tsx is in the diff, with a CSV download affordance added to all three of AccountExtrinsicsSection, AccountTransfersSection, and AccountEventsSection
Each download link/button targets ?format=csv on that tab's own route (/extrinsics, /transfers, /events respectively) — not a shared or wrong-tab URL
The Events tab's CSV link includes the currently-active ev_kind filter when one is set, and omits kind when it isn't
No changes to apps/ui/src/lib/metagraphed/queries.ts, client.ts, or any backend file (src/contracts.mjs, workers/csv.mjs) — the CSV routes and their format=csv support already exist and are out of scope here
Before/after screenshots included in the PR per the standing UI-change rule (this touches visible markup in accounts.$ss58.tsx)
Don't touch the account summary/history/subnets sections (AccountFootprintSection, AccountHistoryChart) — those aren't part of this issue's three named tabs and have no csvRouteQuery-wrapped backend route to export from.
Don't modify the backend CSV routes, csvRouteQuery/csvListQuery helpers, or any src/contracts.mjs / workers/csv.mjs code — the ?format=csv support is already shipped and verified.
Size
Size: S — keep this PR small (aim for ≤10 files / ≤1000 LOC).
Context
AccountDetailinapps/ui/src/routes/accounts.$ss58.tsxrenders three data tables viaAccountEventsSection(Chain events,#events, line 624),AccountExtrinsicsSection(Signed extrinsics,#extrinsics, line 356), andAccountTransfersSection(Transfers,#transfers, line 432) — none of which offer an export affordance. All three backing routes already accept?format=csvpersrc/contracts.mjs:GET /api/v1/accounts/{ss58}/events(line 2416),GET /api/v1/accounts/{ss58}/extrinsics(line 2452), andGET /api/v1/accounts/{ss58}/transfers(line 2469), each wrapped incsvRouteQuery(...). No CSV/download UI exists anywhere inapps/ui/srctoday — this is the first page to wire it up.Requirement
Add a "Download CSV" affordance to each of the three tabs (
SectionAnchorheaders for#events,#extrinsics,#transfers) that links to its own backend route withformat=csvappended (and, for Events, the current?kind=filter preserved), so a visitor can export exactly what the table currently shows.Deliverable
apps/ui/src/routes/accounts.$ss58.tsx— add the affordance to theright={...}slot of theSectionAnchorinAccountExtrinsicsSection(currently only a row-countSectionBadge, line ~364),AccountTransfersSection(line ~440), and insideAccountEventsSection'sright={...}slot alongside the existingSelectFilterfor kind (lines 672-681).DownloadCsvButtoncomponent (no page wiring)"), which as of this writing has landed no component anywhere inapps/ui/src— confirmed via a repo-wide search. FE: wire Download CSV into the Accounts detail page (events/extrinsics/transfers tabs) #3407 must not hand-roll its own<a>/button styling independently of FE: add a reusable DownloadCsvButton component (no page wiring) #3402; land or rebase on FE: add a reusable DownloadCsvButton component (no page wiring) #3402 first, then import and use its component here. If FE: add a reusable DownloadCsvButton component (no page wiring) #3402 is still unmerged when this is picked up, block on it rather than duplicating a bespoke download link.buildUrl(exported fromapps/ui/src/lib/metagraphed/client.ts) to build each download href — it already folds ingetApiBase()(runtime-configurable API origin) andapplyNetworkPrefix()(mainnet/testnet partitioning) and serializes query params, which is exactly what a correct CSV link needs. Do not hardcodeAPI_BASE/origin directly (that snapshot pattern inendpoint-snippet.tsxskips the network prefix and is not the correct precedent here) or hand-build a query string, since that would reintroduce the href-taint-barrier class of bug this codebase already guards against inconfig.ts'ssanitizeApiBase.buildUrl("/api/v1/accounts/{ss58}/extrinsics", { format: "csv" })(ss58-substituted, matching the existingaccountExtrinsicsQuerypath).buildUrl("/api/v1/accounts/{ss58}/transfers", { format: "csv" }).buildUrl("/api/v1/accounts/{ss58}/events", { format: "csv", kind: search.ev_kind })— must reflect the currently-appliedev_kindfilter (fromRoute.useSearch(), already in scope inAccountEventsSection) so the export matches what's on screen; omitkindwhen no filter is active.DownloadCsvButton(or whatever FE: add a reusable DownloadCsvButton component (no page wiring) #3402 names it) pointed at the section's own CSV URL, positioned in the section header'srightslot; clicking it downloads/openstext/csvfor that tab's current rows (events respecting the active kind filter); no change to the JSON data-fetching (accountExtrinsicsQuery/accountTransfersQuery/accountEventsQuery) paths.Acceptance criteria
apps/ui/src/routes/accounts.$ss58.tsxis in the diff, with a CSV download affordance added to all three ofAccountExtrinsicsSection,AccountTransfersSection, andAccountEventsSection?format=csvon that tab's own route (/extrinsics,/transfers,/eventsrespectively) — not a shared or wrong-tab URLev_kindfilter when one is set, and omitskindwhen it isn'tbuildUrlfromlib/metagraphed/client.ts(or the FE: add a reusable DownloadCsvButton component (no page wiring) #3402 component's internal use of it), not a hand-constructed string or a hardcoded API originDownloadCsvButton— no bespoke per-tab download button styling reimplemented in this fileapps/ui/src/lib/metagraphed/queries.ts,client.ts, or any backend file (src/contracts.mjs,workers/csv.mjs) — the CSV routes and theirformat=csvsupport already exist and are out of scope hereaccounts.$ss58.tsx)Non-goals
DownloadCsvButtoncomponent itself here — that's FE: add a reusable DownloadCsvButton component (no page wiring) #3402's scope; this issue only wires it into the three account tabs.AccountFootprintSection,AccountHistoryChart) — those aren't part of this issue's three named tabs and have nocsvRouteQuery-wrapped backend route to export from.csvRouteQuery/csvListQueryhelpers, or anysrc/contracts.mjs/workers/csv.mjscode — the?format=csvsupport is already shipped and verified.Size
Size: S — keep this PR small (aim for ≤10 files / ≤1000 LOC).
Part of #2542.