ci: unified workflow (lint + typecheck + build + rust)#100
Conversation
Switch the TPS Area interpolation from `linear` to `monotone` so the Transaction volume chart renders as a smooth curve instead of connected straight segments between data points.
Revert line interpolation to linear and enable Recharts' built-in animation so newly arriving data points ease into the chart instead of snapping in. This is the smoothing that was actually requested: the visible motion of new points appearing, not the line shape.
Switch the X axis to a continuous time scale with a [now - 5min, now] domain advanced each animation frame, so new points slide in smoothly from the right edge instead of popping into discrete category slots. Keeps isAnimationActive disabled to avoid Recharts re-animation loops on each TPS event. Clamp the domain's left edge to the oldest point so the chart fills immediately instead of showing an empty 5-minute lead-in. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces frontend/pnpm-lock.yaml with main's lockfile minus the duplicate keys introduced by PR #97 (so pnpm 10 can parse it). No package versions change vs main; pnpm install --frozen-lockfile passes. The previous commit on this branch ran a non-frozen pnpm install, which silently re-resolved every floating semver in package.json and produced ~2000 lines of incidental lockfile churn. This commit reverses that.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR consolidates CI into a single unified
Confidence Score: 5/5Safe to merge — the CI wiring is correct, the Rust clippy fixes are mechanical and verified, and the frontend refactors are well-structured with no logic regressions. The workflow change is additive and mirrors the existing lint job patterns. The Rust changes fix all 8 listed clippy warnings correctly. The frontend changes (inflight-block ref map, event-type filtering, sliding TPS chart) are logically sound. The only issue is a team style-rule violation on one useRef call, which has no runtime impact. frontend/hooks/use-block-execution-tracker.ts — contains the useRef style-rule violation; all other files look clean.
|
| Filename | Overview |
|---|---|
| .github/workflows/ci.yml | New unified CI workflow — lint, typecheck, build, and Rust jobs are correctly structured; Rust job installs git before checkout and uses appropriate rust:1.91-slim container with rust-cache. |
| frontend/hooks/use-block-execution-tracker.ts | Major O(N²) → O(1) refactor using a ref-based inflight map; logic is sound, but useRef<number |
| frontend/contexts/events-context.tsx | Adds per-subscriber event-type filtering via ReadonlySet, background-tab message dropping, and useMemo on the context value — all look correct. |
| frontend/components/network-activity-tracker/tps-chart.tsx | Adds rAF-driven sliding window and progressive segment animation via useSlidingNow/drawHistory/buildTicks; intentional 60fps re-renders for smooth chart scrolling, rAF naturally pauses in hidden tabs. |
| backend/src/lib/server.rs | Boxes EventData in the enum variant to fix large_enum_variant; removes needless return and rewrites match-as-bool with matches!(); all changes are safe mechanical clippy fixes. |
| backend/src/lib/event_listener.rs | Renames from_str to from_name (avoids should_implement_trait warning) and replaces % 100 == 0 with is_multiple_of(100); both are correct clippy-driven cleanups. |
| backend/src/lib/event_filter.rs | Changes &Vec to &[T] (ptr_arg fix) and removes a redundant borrow on is_native_transfer (needless_borrow fix); both are correct and safe. |
| backend/src/bin/client.rs | Removes redundant as u64 casts from u64 timestamp subtractions; correct since both operands are already u64. |
| backend/src/lib/serializable_event.rs | Removes .clone() on a Copy type (clone_on_copy fix); trivially correct. |
| frontend/hooks/use-events.ts | Threads eventTypes through to subscribe(); all callers use module-level constants so the dep-array reference is stable — no spurious re-subscriptions. |
| frontend/hooks/use-block-state-tracker.ts | Adds BLOCK_STATE_EVENT_TYPES module-level constant and passes it to useEvents for filtered delivery; no logic changes. |
| frontend/hooks/use-swap-events.ts | Adds SWAP_EVENT_TYPES = ['TxnLog'] filter; hook already only cared about TxnLog events so this is a correct narrowing with no behaviour change. |
| frontend/hooks/use-total-transactions.ts | Adds TXN_HEADER_EVENT_TYPES = ['TxnHeaderStart'] filter; narrows subscription to the only event type the hook processes. |
| frontend/hooks/use-transfer-events.ts | Adds TRANSFER_EVENT_TYPES = ['TxnCallFrame', 'TxnLog'] filter matching what the hook already handled. |
| frontend/package.json | Adds typecheck script (tsc --noEmit) needed by the new CI typecheck job. |
| frontend/pnpm-lock.yaml | Removes duplicate entries introduced by the prior lockfile merge conflict; lockfile is now clean. |
| frontend/pnpm-workspace.yaml | Adds allowBuilds for sharp and unrs-resolver to allow postinstall scripts for those native packages. |
Sequence Diagram
sequenceDiagram
participant WS as WebSocket
participant EC as EventsContext
participant UE as useEvents (hook)
participant H as Consumer Hook
WS->>EC: onmessage(raw)
Note over EC: Drop if visibilityState === hidden
EC->>EC: JSON.parse → ServerMessage
loop for each event in Events[]
EC->>EC: "eventType = evt.payload.type"
loop for each Subscriber
alt "sub.eventTypes === null OR has(eventType)"
EC->>UE: callback(evt)
UE->>H: onEventRef.current(evt)
else filtered out
EC-->>EC: skip
end
end
end
Note over UE: Subscribes with stable module-level eventTypes[] constant
Reviews (6): Last reviewed commit: "fix(backend): resolve clippy lints (#101..." | Re-trigger Greptile
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: frontend | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: pnpm | ||
| cache-dependency-path: frontend/pnpm-lock.yaml | ||
| - run: pnpm install --frozen-lockfile |
There was a problem hiding this comment.
next build runs without required env vars
frontend/config/env.ts exposes NEXT_PUBLIC_EVENTS_WS_URL via getEnvOrThrow, which throws if the variable is unset. While the getter is lazy and won't fire during the webpack compile pass itself, any page that calls publicEnv.EVENTS_WS_URL during server-side rendering or static generation will cause next build to throw and fail the job. Consider adding an env: block (using GitHub Actions secrets) or providing dummy values so the build job gives reliable signal rather than potentially failing for a config reason instead of a code reason.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/ci.yml
Line: 43-57
Comment:
**`next build` runs without required env vars**
`frontend/config/env.ts` exposes `NEXT_PUBLIC_EVENTS_WS_URL` via `getEnvOrThrow`, which throws if the variable is unset. While the getter is lazy and won't fire during the webpack compile pass itself, any page that calls `publicEnv.EVENTS_WS_URL` during server-side rendering or static generation will cause `next build` to throw and fail the job. Consider adding an `env:` block (using GitHub Actions secrets) or providing dummy values so the build job gives reliable signal rather than potentially failing for a config reason instead of a code reason.
How can I resolve this? If you propose a fix, please make it concise.90e1aac to
75e5e79
Compare
…ipeline (#98) **Motivation:** After ~1h on node.monad.xyz the renderer process is killed for OOM. There is no single growing array — every component bounds its state — but at ~200 TPS the per-event fan-out from EventsContext drives enough short-lived allocations to fragment the heap. Backgrounded tabs are worse because the browser does not throttle WebSocket onmessage. **Modifications:** 1. Memoize EventsContext value so consumers don't re-render every time TopAccesses updates. 2. Drop WebSocket messages while document.visibilityState === 'hidden' to avoid running the dispatch + decode pipeline for an invisible tab. 3. Move the in-flight block's transactions out of React state into a ref-backed Map<txnIndex, Transaction>. Per-event updates are now O(1) instead of O(N), and the block is materialized into React state once at BlockFinalized/BlockVerified. 4. Allow subscribers to register an eventTypes filter on subscribe, and apply it at dispatch time so swap/transfer/totals hooks no longer run on BlockStart/TxnHeaderStart/etc. **Result:** Live event dispatch does far less work per WebSocket message, in-flight blocks no longer reallocate their transactions array on every txn event, and a backgrounded tab is effectively idle until it becomes visible again. Co-authored-by: dak-agent[bot] <284037069+dak-agent[bot]@users.noreply.github.com>
e166c0e to
756dbfd
Compare
* feat(tps-chart): smoothly extend the line to each new point Switch the X axis to a continuous time scale whose right edge eases toward the newest point's timestamp each animation frame. A freshly appended point sits just past the edge (clipped by allowDataOverflow) and is revealed sliding in from the right instead of snapping into a discrete category slot; the animation halts once the edge catches up, so the chart is still between points. isAnimationActive stays disabled to avoid Recharts re-animation loops on every TPS event. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: update pnpm lockfile and allow sharp/unrs-resolver builds Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * drawing lines smoothly between the points creation * fix the x absis to have only 1 now --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…orkflow # Conflicts: # frontend/components/network-activity-tracker/tps-chart.tsx
* fix(backend): resolve auto-fixable clippy lints Addresses 6 of the 8 clippy findings surfaced by the new rust CI job: - needless_return (server.rs) - match_like_matches_macro (server.rs) - ptr_arg: &Vec<T> -> &[T] (event_filter.rs) - needless_borrow (event_filter.rs) - manual_is_multiple_of (event_listener.rs) - clone_on_copy (serializable_event.rs) Remaining (require manual judgment, deferred): large_enum_variant (server.rs), should_implement_trait for from_str (event_listener.rs). * fix(backend): resolve non-auto-fixable clippy lints - large_enum_variant: box the 640-byte Event variant of EventDataOrMetrics (Event(Box<EventData>)). Since From::from infers its parameter type from the argument (deref coercion does not apply), the match-site call passes &*event_data to select From<&EventData>; construction uses Box::new(..). - should_implement_trait: rename inherent EventName::from_str -> from_name (and its single caller) so it no longer shadows std::str::FromStr::from_str. * fix(backend): remove redundant u64 casts in client (unnecessary_cast) Surfaced once the lib compiled clean: timestamp_ns is u64, so the (u64 - u64) as u64 casts are redundant; drop the cast and parens.
Replaces
.github/workflows/lint.ymlwith a unified.github/workflows/ci.ymlrunning four jobs:biome ci)tsc --noEmit(frontend)next build(frontend)cargo fmt --check,cargo clippy -D warnings,cargo build(backend workspace)Notes:
lint.ymlis removed; its Biome job is rolled intoci.yml.publish-backend.yml(Docker image publish) is unchanged — this adds build/lint CI for Rust, not publishing.rustjob runs in therust:1.91-slimcontainer (matching the backend Dockerfile) so bindgen's libclang is new enough for the upstream C23 headers from monad-bft. Cargo build is cached viaSwatinem/rust-cache.workflow_dispatch-able from the Actions tab (also run onpull_requestand pushes tomain).Also adds a
typecheckscript (tsc --noEmit) tofrontend/package.json.rust(clippy)cargo fmt --checkandcargo buildpass.cargo clippy -D warningscurrently fails on 8 pre-existing lint issues inbackend/(this code was never clippy-checked —publish-backend.ymlonly builds). We are keeping strict-D warningsand fixing those findings in a separate follow-up PR; therustcheck here is expected red until then. Findings:large_enum_variant,needless_return,match_like_matches_macro,should_implement_trait(from_str),ptr_arg,clone_on_copy,manual_is_multiple_of,needless_borrow.Follow-ups (separate PRs)
rustjob goes green.frontend/) into a single root pnpm workspace with root orchestration scripts — deferred because it needs coordinated Vercel deploy-settings changes.