/** * DAG visualization utilities for 3D rendering. * Transforms API data to react-force-graph-3d format. */ import type { DagVisualization, DagBlock, DagEdge } from './types'; /** Node format expected by ForceGraph3D */ export interface GraphNode extends DagBlock { id: string; val: number; // Node size } /** Link format expected by ForceGraph3D */ export interface GraphLink { source: string; target: string; isSelectedParent: boolean; } /** Graph data format for ForceGraph3D */ export interface GraphData { nodes: GraphNode[]; links: GraphLink[]; } /** Color scheme for block types */ export const BLOCK_COLORS = { chain: '#8b5cf6', // synor purple (chain blocks) blue: '#3b82f6', // blue (honest blocks) red: '#ef4444', // red (potentially malicious/delayed) hover: '#fbbf24', // amber (hover highlight) } as const; /** Edge colors */ export const EDGE_COLORS = { selectedParent: '#fbbf24', // amber normal: '#4b5563', // gray-600 } as const; /** * Transform DagVisualization API response to ForceGraph3D format. */ export function transformToGraphData(dag: DagVisualization): GraphData { const nodes: GraphNode[] = dag.blocks.map((block) => ({ ...block, id: block.hash, val: Math.max(1, block.txCount) * 5, // Node size based on tx count })); const links: GraphLink[] = dag.edges.map((edge) => ({ source: edge.from, target: edge.to, isSelectedParent: edge.isSelectedParent, })); return { nodes, links }; } /** * Get node color based on block type. */ export function getNodeColor(node: GraphNode | DagBlock): string { if (node.isChainBlock) return BLOCK_COLORS.chain; if (node.isBlue) return BLOCK_COLORS.blue; return BLOCK_COLORS.red; } /** * Get link color based on relationship type. */ export function getLinkColor(link: GraphLink | DagEdge): string { return link.isSelectedParent ? EDGE_COLORS.selectedParent : EDGE_COLORS.normal; } /** * Get link width based on relationship type. */ export function getLinkWidth(link: GraphLink | DagEdge): number { return link.isSelectedParent ? 2 : 1; } /** * Format timestamp for tooltip display. */ export function formatBlockTime(timestamp: number): string { return new Date(timestamp).toLocaleString(); }