feat(portfolio): surface degraded/stale chains instead of silent $0#240
Merged
Conversation
The vault discarded Pioneer's portfolio `meta`, so a chain that failed its fresh fetch (node down/timeout) or served cache >5min old showed $0 / a stale value with no way to tell "unavailable" from "genuinely empty." - bun: preserve `meta` per chunk (unwrapPortfolioResponse) and merge across chunks (mergeMetas); after each fetch, push degraded + stale chain names to the webview through the existing pioneer-error channel (severity warning/none) - schema: extend pioneer-error with optional severity + degraded/stale fields (missing severity stays a hard error — back-compatible) - Dashboard: amber soft-fault banner (separate state from the hard-error banner, which supersedes it); window-focus refetch when idle >5min; degraded-chain background retry with 30/60/120/300s backoff - i18n: English strings only; other languages fall back via fallbackLng Server meta is live on api.keepkey.info (pioneer release/v1.3.115).
…ften degraded copy - Banner rendered only the degraded branch; a response with both degraded and stale chains silently dropped the stale warning. Render both lines. - lastFetchAttemptRef seeded at 0 made the first focus event read as 'idle > 5 min' and force-refresh on startup. Seed with mount time. - degradedDesc promised 'last known values', but vault-side chunk failures can render as zeroes. Soften the copy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 12, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The vault discarded Pioneer's portfolio
meta, so a chain that failed its fresh fetch (node down/timeout) or served cache older than 5 min showed$0or a stale value with no way to distinguish "data unavailable" from "genuinely empty." No retry, no staleness signal.Pioneer already emits the needed signal — verified live on
api.keepkey.info(serverrelease/v1.3.115):POST /portfolioreturnsmeta.{degraded, degradedCount, failures[], staleChains[]}. The vault just threw it away inunwrapPortfolioEntries.What changed
Backend (
src/bun/index.ts)unwrapPortfolioResponsekeepsmetaper chunk;mergeMetascombines it across chunks.getBalances, push degraded + stale chain display-names to the webview via the existingpioneer-errorchannel —severity: 'warning'for soft faults,'none'to clear. Degraded = servermeta.failures∪ chains whose pubkeys all landed in a failed chunk.Schema (
src/shared/rpc-schema.ts)pioneer-errorwith optionalseverity+degradedChains/staleChains/staleMinutes. Missingseveritystays a hard error — back-compatible with existing senders.Frontend (
Dashboard.tsx)i18n — English strings only; other 14 languages fall back via
fallbackLng: 'en'.Scope notes
portfolio-faultevent (one source of truth for "balance data problem").windowlisteners insrc/bun— Bun has nowindow).onlyCaipstargeted refetch (full refresh is ~5-6s — not worth the added branching) and therest-pioneer.tschange (that's the external SDK surface, unrelated). Per-row stale indicators deferred.Test plan
tsc --noEmitclean (verified locally — 0 source errors)$0[Dashboard] Retrying degraded chainsin console)