Live Demo URL: https://easypeasy-orcin.vercel.app
easypeasy Money Muling Detection System is a graph-based financial intelligence web application designed to detect, score, and visualize suspicious money movement patterns such as mule cycles, smurfing, and layered shell networks. The system runs entirely in the browser using Next.js and WebGL, constructing a transaction graph, executing detection algorithms client-side, and rendering an interactive visualization for analysts.
The core design goals are:
- High-precision detection of laundering-like structures
- Explainable, evidence-based scoring rather than opaque black-box classification
- Efficient in-browser graph analysis with strong pruning and domain constraints
- Analyst-friendly, interactive visualization and inspection tools
- Framework: Next.js
- Language: TypeScript
- Styling: Tailwind CSS
- Visualization: WebGL (Sigma + Graphology)
- Deployment: Vercel
- Algorithms & Data Structures: Graphology, custom client-side graph analysis modules
The system is organized as a modular, pipeline-style architecture where each stage transforms the data and passes it to the next stage for analysis and visualization.
-
Web Frontend (CSV Upload + UI)
- The user uploads transaction data (e.g., CSV files) and interacts with the application through the web interface.
- Provides controls for loading data, exploring results, and inspecting suspicious accounts and patterns.
-
API Layer
- Acts as the coordination layer between the UI and the internal processing modules.
- Validates inputs, manages data flow between components, and triggers analysis pipelines.
- In the current implementation, this layer is implemented within the Next.js application (client-side), not as a separate backend service.
-
Transaction Processing Engine
-
Parses and normalizes raw transaction data into a structured internal representation.
-
Performs preprocessing such as:
- Timestamp normalization
- Amount parsing
- Basic sanity checks and filtering
-
Produces a clean, analysis-ready transaction dataset.
-
-
Graph Builder
- Constructs a directed, temporal transaction graph from the processed transactions.
- Nodes represent accounts.
- Edges represent transactions, ordered by time.
- Computes auxiliary statistics such as degrees and per-node transaction counts.
-
Pattern Detector (Cycle, Fan, Shell)
-
Runs specialized detection algorithms on the graph, including:
- Cycle detection for mule-layering loops (length 3–5)
- Smurfing detection for fan-in / fan-out burst patterns
- Layered shell detection for multi-hop relay chains of low-activity accounts
-
Outputs detected structures and per-account pattern signals.
-
-
Risk Scoring and Ring Clustering
- Aggregates signals from all detectors and structural/temporal features.
- Computes a suspicion score per account using an evidence accumulation (log-odds) model.
- Groups related suspicious accounts into rings / clusters based on shared patterns and graph connectivity.
-
Output Layer
-
Prepares analysis results for presentation, including:
- Node-level scores and labels
- Detected patterns and clusters
- Metadata required by the visualization layer
-
Acts as the final data interface between analysis and rendering.
-
-
WebGL Renderer (Interactive Graph)
-
Renders the transaction graph and analysis results using WebGL.
-
Visual encodings include:
- Node color by risk level
- Node size by suspiciousness
- Interactive hover and inspection tooltips
-
Enables analysts to explore clusters, cycles, and shell structures visually.
-
- Fully pipeline-driven: each stage has a clear responsibility.
- Modular: detection, scoring, and visualization are cleanly separated.
- Client-side execution: all stages run inside the Next.js application without a dedicated backend.
- Explainable by design: every visual element is backed by explicit graph features and detected patterns.
The primary detection engine identifies directed money-flow cycles of length 3–5 that match realistic laundering and mule-layering patterns. The algorithm enforces:
- Strict temporal forward flow
- Per-hop amount constraints
- Cumulative decay bounds
- Velocity bound
- Merchant / hub exclusion
- Parallel-edge optimization
- Canonicalization
- Subsumption suppression
Pipeline stages:
- Stage 0: Graph construction and eligibility filtering
- Stage 1: Fast-path detection of 3-cycles (triangles)
- Stage 2: Bounded DFS for 4–5 length cycles with heavy pruning
- Stage 3: Merge, canonicalize, and suppress subsumed cycles
- Stage 4: Sort results by cumulative decay (most suspicious first)
Complexity:
Let:
V = number of nodes
E = number of edges
d̄ = average degree after filtering
Graph construction: O(E)
Triangle detection: O(E * d̄) (with strong pruning)
Bounded DFS (length 4–5): Near-linear in practice due to:
- Degree caps
- Temporal pruning
- Amount feasibility pruning
- Lookahead closure checks
Memory: O(V + E) + small caches for parallel-edge resolution
Approach:
For each account:
Maintain inbound and outbound time series
Use a sliding 72-hour window
Track max unique counterparties in any window
If max_unique_inbound > threshold:
Flag as fan-in
If max_unique_outbound > threshold:
Flag as fan-out
Complexity:
Per account: O(T_a) where T_a = number of transactions for that account
Total over all accounts: O(E)
Memory: O(U) per window, where U = unique counterparties in window
Approach:
Define shell account:
total_transactions <= 3
For each start node:
Run bounded BFS up to depth MAX_DEPTH
Track simple paths (no revisits)
When a path reaches MAX_DEPTH:
Inspect intermediate nodes (exclude start and end)
If count(intermediates) >= 2 AND all are shell accounts:
Mark path as layered shell network
Add all nodes in path to shell set
Complexity:
Worst case: O(V * d^MAX_DEPTH)
In practice: much lower due to:
- Small MAX_DEPTH
- Shell filtering
- Early pruning of revisits
Memory: bounded by BFS queue and path storage
Assign each account a deterministic fraud risk score in the range 0–100 such that:
- Scores are comparable across accounts
- Scores remain bounded
- Legitimate vendors are dampened
- Scoring is deterministic and reproducible
X_norm = (X - X_min) / (X_max - X_min + epsilon)
If L in [3, 5]:
cycle_raw = 6 - L
Else:
cycle_raw = 0
fan_raw = max(fan_in_count, fan_out_count)
fan_raw = fan_raw * (1 - vendor_continuity_ratio)
If D >= 3:
shell_raw = D - 2
Else:
shell_raw = 0
If avg_window_tx == 0:
burst_raw = 0
Else:
burst_ratio = max_window_tx / avg_window_tx
burst_raw = burst_ratio
lifespan_days = max_timestamp - min_timestamp
If lifespan_days < 14:
vendor_continuity_ratio = 0
Else:
Split lifespan into equal windows (e.g., 7 days)
Compute tx_counts per window
CV = std(tx_counts) / mean(tx_counts)
continuity_base = 1 - min(1, CV)
lifespan_factor = min(1, lifespan_days / 180)
vendor_continuity_ratio = continuity_base * lifespan_factor
For each feature X:
If X_max == X_min:
X_norm = 0
Else:
X_norm = (X - X_min) / (X_max - X_min + epsilon)
risk_score_0_1 =
0.35 * C_n +
0.30 * F_n +
0.20 * S_n +
0.15 * B_n
Score = 100 * risk_score_0_1
Clamp Score to [0, 100]
If vendor_continuity_ratio > 0.6 AND lifespan_days > 90:
Score = Score * 0.7
Clamp Score to [0, 100]
| Score Range | Risk Level |
|---|---|
| ≥ 80 | Severe |
| 60–79 | High |
| 40–59 | Moderate |
| < 40 | Low |
If all raw features are zero:
Score = 0
If mean window count == 0:
continuity_ratio = 0
If number of windows < 3:
continuity_ratio = 0
All divisions use epsilon to avoid division by zero
- Node.js
- npm
git clone <repository-url>
cd easypeasy
npm i
npm i next
npm run devOpen in browser:
http://localhost:3000
-
Open the live demo or run the app locally.
-
Load or select a dataset of transactions.
-
The application builds the transaction graph in memory.
-
Detection algorithms and scoring run client-side.
-
The UI renders:
- The transaction graph
- Node colors by risk level
- Node sizes by suspiciousness
-
Hover over nodes to inspect:
- Account ID
- Suspicion score
- Risk category
- Detected patterns
-
Use zoom and pan to explore clusters, cycles, and shell structures.
-
All computation runs client-side and is limited by browser memory and CPU.
-
Detection is pattern-based, not a full probabilistic model of financial crime.
-
Adaptive adversaries can attempt to evade fixed structural heuristics.
-
Dataset-relative normalization means scores can shift as the population changes.
-
Very large graphs may cause performance issues in the browser.
-
The system does not currently incorporate:
- KYC data
- Device/IP/geo intelligence
- Cross-platform identity resolution
- Sahil Adit
- Shivraj Patil
- Varad Hajare
- Ojas Deshpande
