synor/apps/explorer-web/src/lib/dagUtils.ts
Gulshan Yadav 48949ebb3f Initial commit: Synor blockchain monorepo
A complete blockchain implementation featuring:
- synord: Full node with GHOSTDAG consensus
- explorer-web: Modern React blockchain explorer with 3D DAG visualization
- CLI wallet and tools
- Smart contract SDK and example contracts (DEX, NFT, token)
- WASM crypto library for browser/mobile
2026-01-08 05:22:17 +05:30

88 lines
2.2 KiB
TypeScript

/**
* 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();
}