Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save shawwn/29ed856d020a0131830aec6b3bc29dc9 to your computer and use it in GitHub Desktop.

Select an option

Save shawwn/29ed856d020a0131830aec6b3bc29dc9 to your computer and use it in GitHub Desktop.

Handoff: brownie-viz-graph-interactivity

What was accomplished

Improved the Transfer Graph demo in the brownie-viz webapp with node selection/pinning, edge highlighting, visibility filtering, and various rendering fixes.

Features added

  • Pin/unpin nodes: Clicking a node "pins" it — hides all other nodes and edges except the pinned node and its direct neighbors. Clicking the same node or empty space unpins.
  • Gold highlight for active nodes: Hovered or pinned nodes turn yellow/gold (1.0, 0.7, 0.15) to match the orange-gold edge highlight color.
  • Edge hiding on pin: When a node is pinned, non-connected edges are set to black (invisible with additive blending). Connected edges stay orange-gold.
  • Hidden node offscreen trick: Hidden nodes are moved to (1e7, 1e7, 1e7) in addition to being scaled to 0, to prevent bloom post-processing artifacts.
  • Stars color changed: Background star particles shifted from blue (#334466) to warm red (#664444) so they aren't confused with graph nodes.

Bugs fixed

  • Nodes not restoring after unpin: Instance matrices were only updated when visibleSet was truthy. After unpin (visibleSet becomes null), matrices stayed at scale 0. Fix: always update matrices regardless of visibleSet.
  • computeBoundingSphere(): Called after every matrix update to keep the raycaster's bounding sphere current.

Files changed

  • apps/brownie-viz/frontend/src/components/GraphView.tsx — All changes are in this file: GlowNodes (visibility, gold highlight, matrix restore), EdgeLines (pin-aware edge hiding), GraphScene (visibleSet computation, prop passing), Stars (color change).

Commits / branch

  • 125fb27 brownie-viz: pin/unpin visibility, gold highlight for active nodes

Branch: eth-optimization (pushed to origin).


Key decisions

Stars vs nodes confusion

The user reported "isolated nodes" that couldn't be hovered. After debugging (10x size + red color for isolated nodes, green for stars), these turned out to be background Stars particles, not graph nodes. Stars are <points> with <pointsMaterial> and have no pointer event handlers. Fix was cosmetic: changed star color hue to red-ish so they're visually distinct from blue graph nodes.

Isolated nodes are kept in the graph

The user explicitly rejected filtering out edgeless nodes (nodes in top-N by volume but with no edges within the top-N set). These represent high-volume wallets whose counterparties are all outside the top-N. The user wants them visible and interactive. A change to graph.go that filtered them was reverted.

Additive blending for hiding

Hidden nodes use color (0,0,0) which adds nothing with AdditiveBlending, plus scale 0 and position (1e7,1e7,1e7) for belt-and-suspenders invisibility. This prevents bloom from picking up residual fragments.

Node size formula

Current: 2.0 + Math.pow(t, 0.5) * 10.0 where t is 0..1 on log(volume). Was briefly changed to 4.0 + 8.0 for debugging but reverted since the "unhittable nodes" were actually Stars particles, not small graph nodes.


Important context for future sessions

Architecture recap

  • Backend: Go server reads brownie store, serves JSON APIs. Graph data is lazily cached per token mint in Server.graphCache. sliceGraph() cheaply extracts top-N from the precomputed rawGraph.
  • Frontend: React + Vite + Three.js via @react-three/fiber. InstancedMesh for nodes (additive-blended sprites), LineSegments for edges.

R3F stale closure pattern

All callbacks passed into the R3F <Canvas> use useRef to avoid stale closures (R3F uses a separate React reconciler). The pattern:

const hoverRef = useRef((idx, e) => {})
hoverRef.current = (idx, e) => { /* uses current state */ }
// Pass hoverRef into Canvas, call hoverRef.current inside

HMR + R3F is unreliable

Hot module reload with React Three Fiber frequently breaks pointer events and scene state. Full page refresh is needed after code changes. This is a known limitation, not a bug in our code.

Render-phase side effects

The GlowNodes component updates instance matrices and colors during React's render phase (not in useEffect). This is technically not React-idiomatic but works because R3F applies changes to Three.js objects. The matrices are rewritten every render when visibleSet/activeNodeId/pinnedNodeId change.

Branch status

  • eth-optimization is current, pushed to origin, no pending uncommitted changes (aside from the stars color change and computeBoundingSphere fix which haven't been committed yet).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment