/**
* Visual flow diagram showing transaction inputs and outputs.
* Creates a Sankey-style visualization of fund flow.
*/
import { Link } from 'react-router-dom';
import { ArrowRight, Coins, Wallet, Gift } from 'lucide-react';
import { truncateHash, formatSynor } from '../lib/utils';
import type { ExplorerInput, ExplorerOutput } from '../lib/types';
interface TransactionFlowDiagramProps {
inputs: ExplorerInput[];
outputs: ExplorerOutput[];
isCoinbase: boolean;
totalInput: number;
totalOutput: number;
fee: number;
}
export default function TransactionFlowDiagram({
inputs,
outputs,
isCoinbase,
totalInput,
totalOutput,
fee,
}: TransactionFlowDiagramProps) {
// Calculate percentages for visual sizing
const maxValue = Math.max(totalInput, totalOutput);
return (
{/* Background gradient */}
{/* Header */}
Transaction Flow
{!isCoinbase && fee > 0 && (
Fee: {formatSynor(fee, 4)}
)}
{/* Inputs Column */}
Inputs
{isCoinbase ? (
) : (
{inputs.map((input, i) => (
))}
)}
{/* Total input */}
{!isCoinbase && (
Total Input
{formatSynor(totalInput, 4)}
)}
{/* Center Flow Arrow */}
{/* Animated flow lines */}
{/* Background track */}
{/* Animated particles */}
{/* Central transaction icon */}
{/* Top fade */}
{/* Bottom fade */}
{/* Outputs Column */}
Outputs
{outputs.map((output, i) => (
))}
{/* Total output */}
Total Output
{formatSynor(totalOutput, 4)}
{/* Flow summary bar */}
{/* Input portion */}
{/* Output portion */}
{/* CSS for flow animation */}
);
}
function CoinbaseInput() {
return (
Block Reward
Coinbase Transaction
);
}
interface InputNodeProps {
input: ExplorerInput;
percentage: number;
}
function InputNode({ input, percentage }: InputNodeProps) {
const barWidth = Math.max(20, Math.min(100, percentage));
return (
{/* Value bar background */}
{input.address ? (
{truncateHash(input.address, 8, 8)}
) : (
Unknown
)}
{input.value !== undefined && (
-{formatSynor(input.value, 2)}
)}
);
}
interface OutputNodeProps {
output: ExplorerOutput;
index: number;
percentage: number;
}
function OutputNode({ output, percentage }: OutputNodeProps) {
const barWidth = Math.max(20, Math.min(100, percentage));
return (
{/* Value bar background */}
{output.address ? (
{truncateHash(output.address, 8, 8)}
) : (
{output.scriptType}
)}
+{formatSynor(output.value, 2)}
);
}