Analytical, diagnostic, and forensic capabilities
Accepts structured JSON log exports, plain text, and mixed-format files via drag-and-drop or file picker. Input extensions: .json .txt .log
Three-tier parser: The parser attempts structured parsing first, falling back to a recovery parser for malformed JSON, and finally a brace scanner that extracts parseable JSON objects from corrupted or partially-truncated files. Handles UTF-8 BOM and normalizes top-level arrays vs. objects.
Mobile log synthesis: When exportLogsMeta is absent (mobile log format), the parser reconstructs metadata β platform, app version, and account IDs β from bridge schedule messages embedded in the event stream.
Post-parse normalization: All entries are chronologically sorted and assigned a stable logIndex used as the universal cross-reference key throughout the tool. Reverse-chronological mobile exports are detected and reversed before indexing.
Tested with logs containing 15,000+ entries. All parsing runs client-side in the browser β no data is transmitted to any server during parsing.
Automated quality scoring on a 0β100 scale evaluates log completeness across four independent dimensions:
Grade thresholds: Excellent (85+), Good (65+), Fair (40+), Poor (<40). Each dimension contributes a weighted sub-score; the breakdown is available for granular assessment.
Mobile log normalization adjusts expectations for platform-specific data gaps β mobile logs are not penalized for absent sync data that is structurally unavailable on that platform.
Multi-source identification with automatic fallback chain. The extractor attempts each method in order, stopping when both modelId and fw are resolved:
Supported devices: Nano S, Nano X, Nano S Plus, Stax, Flex (europa), Nano Gen5 (apex). Firmware version extraction includes update availability detection when the current firmware can be compared against the latest known release.
Software version-aware branding: Detects whether the session used "Ledger Live" (v2.x) or "Ledger Wallet" (v4.x) via userAgent parsing and version number analysis. All diagnostic text adjusts accordingly.
Extracts device communication commands from log entries. Each APDU record includes command direction (sent to device / received from device), raw instruction byte, and status code.
Status code interpretation:
TLV parsing: GetAppAndVersion responses (instruction B001) are parsed as Tag-Length-Value structures to identify which applications were open on the device during the session.
Rejection counting and summary generation per session. Supports both the legacy APDU format and the LLv4 Device Management Kit (DMK) logger format used in Ledger Wallet 4.0+.
Three detection methods with priority fallback:
Required app inference: Account currencies are mapped to the device applications they depend on (via a 46-entry CURRENCY_TO_APP map). Each inferred required app is compared against the detected installed set to produce status classifications: installed + current, installed + outdated, or not installed.
Chain enrichment: When 2 or more accounts require the same device app, the app row lists all dependent chain tickers. Missing or outdated apps are surfaced as visual indicators on account cards.
Every log entry is classified by type: action, analytics, bridge, countervalues, error, network, persistence, walletsync, live-dmk-logger, and others. Each type is assigned a consistent color used identically across all visualizations β session strip bars, row type badges, legend chips, Issues strip, and ErrCard breadcrumbs.
Type color palette (TC constant):
Per-entry metadata extraction: timestamp (normalized from date or timestamp field), type, log level, message string, structured data payload, query arguments, payload fields, and embedded error objects.
Session boundary detection: first and last timestamps establish total session duration. Entry count and type diversity contribute to data quality scoring.
The session is divided into 80 equal time buckets. Each bucket renders as a stacked bar where bar height represents event density (total entry count) and color segments represent event type distribution, using the same canonical color map as row badges.
Visual treatment: Bar tops have rounded corners (border-radius: 2px 2px 0 0). The strip container has a flat background matching the panel color. Bars render at 0.92 opacity. The strip reveals left-to-right via clip-path: inset() animation (stripDraw) on tab enter.
Legend chips: One chip per event type present in the session, showing type name, color dot, and entry count. Each chip uses a tinted background and border in its own TC color at low opacity. Hovering a chip dims all non-matching bar segments to 15% opacity. Clicking a chip filters the entry list to that type. State is shared with the type dropdown filter β changes in either update both.
Error dot baseline: Error entries are rendered as individual colored dots on a dedicated baseline below the bars. Each dot is a clickable navigation target β click scrolls to and expands that entry in the list.
Bucket hover tooltip: Hovering any bar shows timestamp, total event count for that bucket, per-type breakdown, and sample message. Clicking the bar scrolls to and expands the nearest log entry to the bucket's midpoint.
Consecutive same-type events within a 1.5-second temporal window are automatically collapsed into expandable group headers. Group headers display: event type, repeat count, time range, and total duration.
Minimum group size: 3 events β sequences smaller than this remain as individual rows. Error entries are unconditionally excluded from grouping and always appear as individual rows regardless of proximity or type match.
Groups are keyed by the logIndex of the first entry in the group, allowing stable expand/collapse state across filter changes. Toggleable between Grouped (default) and Flat mode via a header button.
Typical compression ratio: 50β70% reduction in visible rows on standard production logs (e.g., 2,500 raw entries β approximately 80 visible rows after grouping).
Filters the full event stream to entries that reference a specific account. The matcher performs case-insensitive substring search across five fields per entry: message string, type string, serialized data payload, serialized query arguments, and serialized payload fields.
Match criteria (OR logic across fields, AND with other filters):
Activated from the Accounts section via Shift+click on a health tile or the Timeline button on account cards. A filter banner in the Timeline header displays the active account and provides one-click clear. Combines with type filter and text search as AND logic.
82-pattern error knowledge base. Each pattern specifies a matching strategy (regex or substring), category (Hardware / Software / Server), severity (Critical / Warning / Info), diagnostic title, recommended agent action, and list of common causes.
Priority matching: When multiple patterns match a single error entry, the highest severity match is selected. Within the same severity, the match with the longer match string wins (specificity tiebreaker).
APDU subcode extraction: When a generic transport error is detected, the system scans the error data and message for embedded hexadecimal status codes and attempts a secondary pattern match against the more specific code. This converts generic "device communication failed" errors into actionable diagnoses when the specific rejection code is present.
Unmatched errors are classified as "Unexpected error" (Info severity) with full raw data preserved for manual inspection via the Raw JSON viewer.
ERR_DB text localization: All diagnostic advice text undergoes runtime substitution β "Ledger Live" is replaced with "Ledger Wallet" when the session brand is detected as the newer product, without modifying the knowledge base array itself.
Error clustering analysis computes the time span between the first and last error relative to total session duration. Automatic plain-English interpretation is generated:
Repeat detection: Errors sharing the same diagnostic title are counted and grouped. When a pattern appears 2 or more times, it is surfaced as an interactive badge in the Issues header (e.g., "β» Price data unavailable Γ4"). Clicking a badge applies a pattern filter to the error list.
For each error entry, the 5 immediately preceding log entries are locatable by scanning backward through the full entry array from the error's logIndex. These entries are renderable as a breadcrumb trail in the error detail panel.
Each breadcrumb shows: relative time offset from the error (e.g., β0.3s), event type with a TC-colored badge matching the type badge system used throughout the tool, and a truncated message string. The final row in the trail is the error itself, highlighted in the error's severity color.
One-click navigation from any error detail panel to the error's position in the full Timeline β this navigation clears all active Timeline filters and grouping to guarantee the target entry is visible, then scrolls to it.
Below the breadcrumbs, a Diagnostic Pathways section renders correlated evidence from the pre-error window. See Diagnostic Pathways for the computation details.
Automatic scanning of error messages, structured data payloads, and raw payload fields for strings matching known account addresses. When a match is found (candidate string β₯ 8 characters), the error is linked to the corresponding account.
Linked accounts appear as interactive navigation chips on error detail cards. Clicking an account chip navigates to that account in the Accounts section. The correlation map is computed once at log load time using a Map<logIndex, account> structure keyed on entry position.
The reverse pathway also exists: clicking an error badge on an account card in the Accounts section navigates to the Issues section with a filter applied to show only errors associated with that account's address.
Severity filter chips (Critical / Warning / Info) and category filter chips (Hardware / Software / Server) are rendered in the Issues section header. Clicking a chip applies that filter. Filters combine with AND logic β activating Critical + Hardware returns only errors that are simultaneously critical severity and hardware category.
Hover interaction: Hovering a severity chip dims non-matching error indicators on the session strip in real time, without applying a persistent filter. Hovering a category chip produces the same effect for the category dimension. This enables visual inspection of distribution before committing to a filter.
Error session strip: Stacked bars using the same 80-bucket system as the Timeline strip. Context (non-error) segments use the TC type color palette at 35% opacity β same orange for bridge, blue for network, purple for analytics. Error segments render at full opacity with a red (T.error) glow. This means the strip simultaneously shows where in the session errors occurred and what else was happening around them. Hovering any bar renders a tooltip showing the timestamp, error count, total event count, and error details for that bucket. Clicking selects the nearest error. When Focus Mode is active, non-focused error segments dim to 20% opacity.
Primary extraction from SyncSuccess analytics events (Ledger Live / Ledger Wallet 2.xβ3.x format). Each event carries per-account sync duration, operation count, and reported balance. Secondary extraction from bridge sync sessions (Ledger Wallet 4.0 / LLv4 format).
LLv4 bridge sync fallback: When no SyncSuccess analytics events are present, the extractor scans for type: "bridge" entries containing "SyncSession finished". When found, the total session duration is applied as a sync duration across all accounts, preventing false "no sync data" alerts on newer log formats.
Per-account data extracted: chain identification, address, derivation mode, operation count, log-reported balance, spendable balance, sync duration, token list with contract addresses and operation counts. Account IDs extracted from exportLogsMeta.accountsIds for cross-referencing with external systems.
Three chains store non-explorer-compatible credential formats in logs. The tool automatically converts these to usable addresses:
Derived addresses are surfaced with copy buttons and direct block explorer links. All three conversions run entirely client-side with no external API calls.
Full BIP32 hierarchical deterministic key derivation for Bitcoin, Litecoin, Dogecoin, Bitcoin Cash, and Zcash (transparent t1 only β Ledger does not support shielded signing). Derives individual addresses from xpub, ypub, and zpub keys along receive (m/0/i) and change (m/1/i) chains.
Supported derivation modes:
Per-address live balance query and transaction count via public blockchain APIs. Gap limit detection: scanning stops after consecutive unused addresses are found (gap limit = 20 for receive chain, configurable). Rate limiting handled with automatic retry up to 5 times with exponential backoff.
Per-address explorer links for independent on-chain verification. Uses bitcoinjs-lib 5.2.0 for address derivation, running entirely in the browser via bundled library.
Accounts sharing the same Ethereum-format address (hex strings β₯ 20 characters) are automatically identified as an EVM group. This is common when a customer uses Ethereum alongside L2 and EVM-compatible chains (Polygon, Arbitrum, Optimism, BSC, Base, etc.) that share the same address space.
Group rendering: shared address header with copy button, chain tile count, and combined fiat value aggregated across all accounts in the group. The Ethereum account sorts first within each group; remaining chains sort by fiat value descending.
Grouping is applied after the full account list is rendered β individual account cards within a group retain their full detail, error badges, and xpub scan buttons.
Per-account health tile with chain-colored background derived from the chain registry color. Each tile displays a brand icon loaded from CDN (simplr-sh/coin-logos, keyed by COINGECKO_IDS) with a 3-letter ticker label as fallback when no icon is available. Tile opacity reflects account status: funded (full), empty (reduced), no sync data (amber border).
Corner indicator system:
Hover popover: chain name, truncated address, live balance and fiat value, sync status (no sync / loading / empty), derivation mode, error count, and xpub/explorer availability flags. Popover has onMouseEnter/onMouseLeave handlers to stay visible when the cursor moves from the tile to the popover. Clamped to container width.
Adaptive dimming: When account focus is active, non-focused tiles dim to 25% opacity with a 0.2s transition. The focused tile displays a focusPulse CSS animation (scale + opacity breathing). See Adaptive Dimming for full details.
Portfolio overlay: Activated via "Portfolio βΈ" button. Tiles are resized proportionally to fiat value (36β80px) and sorted by value descending. Clicking any tile applies a chain filter and closes the overlay.
Automatic balance retrieval for 40+ blockchain networks from public APIs. No API keys, authentication, or server-side components required. All requests originate from the user's browser.
Coverage by tier:
Fiat pricing: CoinGecko API with chain currency IDs mapped via a 40+ entry COINGECKO_IDS constant. USD prices batch-fetched after balances complete.
Request staggering at 200ms intervals to avoid rate limiting. Per-account status tracking: loading, ok, error, unsupported. Portfolio aggregation: sum of all accounts' fiat values available in the sidebar and Accounts section Portfolio overlay. Accounts with unsupported status are identified with a ? indicator on health tiles.
Token metadata is resolved on-demand from Ledger's CAL service (crypto-assets-service.api.ledger.com/v1/tokens?id=β¦) when an account card expands. Each token's contract_address, decimals, ticker, and name are cached in localStorage with a 24-hour per-token TTL (ldt_tkm_v1). Live token balances come from a single Multicall3.aggregate3 call per chain (one round trip for N tokens). Live USD prices come from DexScreener (/latest/dex/tokens/{contract}) with concurrency 5, a 200ms minimum gap, and a session-scoped 5-minute price cache. Per-chain URL builders (TOKEN_URLS) generate direct explorer links; TOKEN_SEARCH handles search-fallback for chains without exact resolution.
Token badges on account cards are rendered as clickable links. Token operation counts from log sync data are preserved per token per account. EVM chain IDs are mapped via a 22-entry EVM_CHAIN_IDS constant used to construct the correct explorer URL for each network.
The following data correlation pathways are implemented as direct navigation actions:
Single-account investigation mode controlled by the focusedAcct state variable in the App component. Holds the full account object (with addr, ch.color, ch.ticker) or null when inactive.
Activation triggers:
Downstream effects: A useEffect propagates focusedAcct to tlAcctFilter (Timeline account filter) and errAcctFilter (Issues account filter). Visual effects are applied via inline opacity styles on non-focused elements.
Visual indicators: Sidebar focus indicator (purple pill with chain color swatch and ticker), content area left border (3px, chain color), focusPulse CSS animation on the focused tile (scale 1β1.08 + opacity breathing at 2s interval).
Clear triggers: Escape key, β on sidebar indicator, β on Context Ribbon, Shift+click same tile. State is also reset in handleFile and clearLog.
Computed navigation bar at the top of the content area. No dedicated state variable β rendered from existing focusedAcct, selectedErr, and section state.
Visibility condition: focusedAcct is set OR (selectedErr is set AND section === 'errors').
Segments:
Clear button: Wipes both focusedAcct and selectedErr.
Automatic correlation of pre-error events rendered within the ErrCard component. Implemented as a useMemo with dependencies [entries, err.li, err.ts].
Computation: Scans a 5-second window before each error's timestamp. Counts events in four categories:
Returns null if no correlated events are found in the window. When results exist, renders clickable "Related evidence" links: network failures β Network section (onGoNetwork), APDU rejections β APDU section (onGoApdu), sync entries β Timeline via jumpTo(syncEntry.logIndex).
Visual de-emphasis of non-focused elements when focusedAcct is active. Applied via inline opacity styles with transition: opacity 0.2s.
Opacity values by element type:
Content area receives a 3px left border in the focused account's chain color. The focused tile gets the focusPulse keyframe animation (scale 1β1.08, opacity 0.85β1, 2s ease-in-out infinite).
Design principle: Non-focused elements dim but remain visible β context is preserved, not hidden. This allows peripheral awareness of the full dataset while directing attention to the investigation target.
Two-zone vertical layout within a flex column container (Zone 3 bottom bar was removed):
Zone 1 β Triage row (flexShrink:0): No-sync warning banner (conditional), device status line (compact one-liner: model Β· firmware status Β· app count status Β· sync status), stat badges row (Issues hero with severity-colored left border, Accounts, Network with failure count, Log Quality with score), action bar (Focus Investigation dropdown, Copy report dropdown, Guide π button, activity badges).
Zone 2 β Content (flex:1, overflow:hidden, overflowY:auto): Two-column layout when findings exist. Left column: unified device card. Right column: Diagnostic Priority Map β a squarified treemap of all findings from 7 data sources (log errors, firmware status, app version, device app status, no-sync flag, network failures, incomplete swaps). Blocks sized by severity weight, colored by severity (red / amber / green). Interactive category chips (Connection, Sync, Activity, App & Updates, Server) filter the treemap. Each block is clickable and navigates to the relevant section. When no errors and no system findings: device card spans full width with green "no issues" confirmation. See Diagnostic Priority Map for detailed architecture.
Stat badge computation: Issues badge shows count with severity-based label and color. Network badge counts entries with status β₯ 400 or level='error'. Quality badge shows the computed 0β100 score. All stat numbers use clamp(28px, 4vh, 42px) sizing.
A squarified treemap rendered in the right column of the Overview when findings exist. Uses the same squarify() module-scope algorithm as the Accounts portfolio overlay.
Findings engine (IIFE in Overview render): Collects findings from 7 sources into a flat findings[] array:
Workflow categories (DIAG_WF constant, classifyDiag(dg) function β both at module scope): Five categories: connection, sync, activity, app, server. Classification uses ERR_DB cat field combined with title-string heuristics to resolve ambiguous software-category errors.
State: diagTmSize {w, h} measured via ResizeObserver + getBoundingClientRect + requestAnimationFrame on the container ref (diagTreemapRef). diagCatFilter (nullable category string). Observer dep array: [section, logData] to re-measure on navigation and file load.
Block rendering: Each block is positioned absolutely with left/top/width/height from squarify output. CSS transitions on all four coordinates at 0.3s ease enable animated reflow when category filter changes. Color: severity color at 40% opacity background + 3px left border at full color. key={f.id} is a stable string ('err-'+title, 'fw-outdated', etc.) ensuring DOM element reuse across filter changes and enabling CSS transition animation.
Focus Mode integration: Per-block relevance: errRelevant = focusedAcct ? (f.linkedAccts.length===0 || f.linkedAccts.some(a => a.addr === focusedAcct.addr)) : true. Non-relevant blocks dim to opacity:0.12. System-wide findings (linkedAccts.length===0) always remain fully visible regardless of focus state.
Reset: setDiagCatFilter(null) called in both handleFile paths and clearLog.
Three independent balance data sources are available simultaneously:
Comparison across these sources enables detection of:
Customer View balance comparison model: Agent Insights implements a three-layer comparison: (1) crypto comparison using spendableBalance vs live balance, (2) fiat comparison using the customer's cached rate for both columns, and (3) market value via CoinGecko shown as supplementary. Staking detection prevents false positives on 18+ account types. See Agent Insights Engine for details.
Customer View merges data from two sources: log-extracted accounts (logData.accts) and app.json accounts (appJson.accounts). The merge is performed in a useMemo inside the CustomerView component, producing enrichedAccts.
Merge strategy: Log accounts are the base. For each log account, the pipeline searches for a matching app.json account by id. When matched, the following fields are overlaid:
When app.json contains accounts not present in the log, they are appended as app.json-only accounts with enriched:true and synthetic chain metadata derived from the currencyId.
For investigation workflows, see the Agent Guide (π button) β Customer View.
The countervalue system extracts cached exchange rates from the customer's app.json to display fiat values exactly as the customer saw them.
Rate extraction: cvGetRateMap(appJson) builds a map of {fiatCurrency} {cryptoId} β {date: rate} from the app.json's countervalue cache. The latest rate per asset is retrieved by cvLatestRate(appJson, cid) which returns {rate, date}.
Fiat conversion: cvFiatValue(appJson, cid, rawBalance) computes the fiat value using the customer's cached rate. This produces the exact dollar amount the customer saw in their app β not the current market price.
Display formatting: cvFmtFiat(value, appJson) formats values using the customer's preferred fiat currency and locale settings. countervalueFirst setting is respected throughout β when enabled, fiat values appear above crypto values.
Rate-on-date: cvRateOnDate(appJson, cid, dateStr) retrieves the rate for a specific date, enabling per-operation fiat valuation in the transactions timeline.
The Agent Insights findings engine is a single useMemo that produces a severity-sorted array of diagnostic findings from all available data sources.
Finding types:
Balance comparison model:
Severity classification: red = balance mismatch or pending transactions. amber = failed transactions, log errors, developer mode, data issues. green = healthy checks. Sorted red β amber β green.
Visual elements: Health dots strip (one dot per account, colored by status, clickable), comparison bars (proportional width showing customer vs on-chain), portfolio donut (44Γ44px SVG with overlapping arcs).
Automatic detection of account drains within the Agent Insights findings engine. A drain is classified when an account's live balance has dropped more than 90% compared to the customer's cached balance, and the cached balance had real value (above $50 fiat).
Per-account classification: Inside the existing per-account findings loop, each account is evaluated for drain status. Drained accounts receive a _isDrained flag, a "DRAINED" badge, and drain-specific detail text and escalation guidance replacing the generic "Balance changed" messaging.
Cross-account aggregation: After the per-account loop, all drained accounts are collected. If two or more accounts are drained, the system classifies this as a seed compromise β the recovery phrase is likely exposed. A summary kind:'drain' finding is created via f.unshift() to appear at the top of the findings list.
Operation scanning: For each drained account, the ajOperations array is scanned for OUT transactions. Each operation's recipients[], hash, date, and value are extracted. Token sub-account operations are also scanned when the token balance is zero but operations exist.
Recipient aggregation: All recipient addresses from drain transactions across all drained accounts are collected and deduplicated (case-insensitive). On EVM chains, the same address receiving from multiple chains (e.g., ETH, Polygon, Arbitrum) is identified as a single collection wallet. The customer's own addresses are filtered out. Remaining addresses are the attacker's endpoints.
Fund flow visualization: A visual diagram renders in the drain detail panel: source accounts (chain-colored, left column) connected via gradient lines to destination addresses (red-tinted, right column). Multi-chain convergence to a single address is highlighted. Each connection includes transaction explorer links via TX_EXPLORERS, and each destination address includes an address explorer link via CHAINS[].url.
Forensic copy report: A formatted plain-text report optimized for law enforcement escalation. Includes: customer identity (user ID, device), per-account drain details (address, before/after balance, drain transaction hashes with explorer URLs, recipient addresses), total loss across all chains, and all attacker endpoint addresses with explorer links.
Staking chain guard: When drained accounts are on chains that support native staking (checked against STAKING_APY), an amber warning advises the agent to verify on the block explorer before escalating β the balance drop may be from post-export staking rather than theft.
Staking is detected when ajBalance β ajSpendable for an account. The staked amount is balance - spendableBalance. This affects 18 of 96 accounts in the test dataset.
Chain-specific handling:
Comparison adjustment: when staking is detected, the findings engine compares spendableBalance to live balance instead of balance. This eliminates false positives. The staked amount is shown as informational context, not as a discrepancy.
The Earn tab extracts staking data from enrichedAccts without any live API calls.
Native staking positions: accounts where balance β spendableBalance. Staked amount, fiat value, staking operation history (DELEGATE, STAKE, FREEZE, VOTE, UNDELEGATE, UNSTAKE, WITHDRAW, REWARD), validator addresses from op.recipients and op.extra.stake.address.
Liquid staking tokens: detected by pattern-matching tokenId strings in sub-accounts against known LST identifiers: steth, coinbase_wrapped_staked_eth, jupiter_staked_sol, lombard_staked_bitcoin, lc_staked_shared_eth, reth. Decimals for known tokens come from CAL metadata (authoritative); the TOKEN_DECIMALS_PATTERNS regex array is a fallback for tokens not yet looked up in CAL.
Estimated APY rates: stored in a constant STAKING_APY map derived from Ledger's public documentation. SOL ~5-7%, ATOM ~15-20%, DOT ~10-12%, XTZ ~5%, TRX ~3-5%, NEAR ~8-12%, ADA ~3-5%, ALGO ~5-7%, ETH ~3-3.5%.
Known providers: Ledger by Figment (SOL, ATOM, DOT, NEAR), Kiln (ETH), Lido (ETHβstETH), Coinbase (ETHβcbETH), Yield.xyz (AVAX, DOT, TRX, POL, BNB, CRO).
CVPortfolio β asset allocation table with 5-column grid (Asset, Price, Allocation with colored progress bar, Balance, Value). Chain groups sorted by fiat value. Clickable rows navigate to Accounts. Recent dApp activity from discover.recentlyUsed.
CVAccounts (list) β horizontal grid rows: icon (52px), chain+name, β checkmark, crypto balance, fiat value, change %, star β/β . Token expansion inline. Search + sort by balance/name.
CVAccounts (detail) β balance hero (crypto + fiat, respects countervalueFirst), rate reference, action button pills, staking split display, operations timeline grouped by date (3-column grid: icon + label/time/counterparty + right-aligned amount/fiat), swap history, token balances with per-token operations.
CVEarn β "My rewards"/"Earn opportunities" tab bar. Summary cards (total deposited + allocation bar, total rewards + since date). Deposited assets table (4-column grid). Expandable detail per position: validators, balance breakdown, staking operation timeline. Liquid staking tokens section. Provider list on "Earn opportunities" tab.
CVMyLedger β device card with model/firmware/genuine check. Storage bar with proportional colored segments per app. App catalog with version comparison (installed/outdated/missing).
CVAgentInsights β fixed-viewport master-detail dashboard. Row 1: header + KPI chips + filter toggle. Row 2: 4 stat cards. Row 2.5: health dots strip. Row 3: findings list (left 38%) + detail panel (right 62%). First finding auto-selected. overflowY:'hidden' on .cv-content when active.
Extraction and display of all HTTP requests captured in the log. Each request record includes URL, HTTP method, status code, and associated error data when present.
Status code classification: success (2xx), client error (4xx), server error (5xx). Error summarization at the section header level: total error count with server vs. client error breakdown. This enables rapid determination of whether failures were caused by server-side problems or client configuration issues.
Request URLs are displayed in full and are useful for identifying which Ledger or third-party APIs were contacted during the session, including firmware update endpoints, Manager API calls, and pricing service requests.
Automatic detection of significant user activities during the session based on analytics event and log entry patterns:
Analytics event parsing: App Start metadata captures user ID, OS, platform, device model, and app version at session open. Portfolio analytics events record portfolio metrics at session time. SyncSuccess events capture per-account sync outcomes including operation count and balance.
Software version-aware branding: The tool detects whether the session originated from "Ledger Live" (versions 2.46β~2.131) or "Ledger Wallet" (versions ~2.132+, 4.0+). Detection uses userAgent string parsing from exportLogsMeta with version number fallback. All labels, error advice text, and session descriptions adjust to reflect the correct product name.
Six export formats, all generating plain text optimized for copy-paste into support systems:
All copy formats include live blockchain balances and fiat values when available. Formats that include account data add a β NO SYNC DATA warning line when the log contains no sync information, so recipients are aware of the data source limitations.
All log parsing, analysis, pattern matching, and data correlation runs entirely in the browser via client-side JavaScript. No log data is transmitted to any server under any circumstance.
External contacts made during analysis (addresses only, no log content):
No cookies are set. No data is written to localStorage or sessionStorage. No analytics or telemetry of any kind. The tool can operate fully offline except for live balance fetching and fiat pricing β all other features function without network access.
The Ledger Diagnostic Toolkit is a single-file client-side web application (~8,400 lines of HTML, CSS, and JavaScript) that runs entirely in the browser with no build step, no server, and no installation. It opens as a local file:// or from any static host.
Architecture highlights: