The investigator's reality
When fraud hits a Nigerian bank, here is what actually happens: the EFCC or the police sends a request with a deadline. Trace where the stolen ₦40 million went. A compliance analyst then manually queries account after account, hopping between systems, building a spreadsheet, trying to reconstruct the flow.
This takes days. Meanwhile the money is gone.
The typical pattern: money leaves the victim's account, bounces through 2 to 4 accounts (often within the same bank, where instant intra-bank transfers are fastest), then exits via NIP to other banks. The first few hops are within the bank's own book, fully visible in their transaction data.
The insight
Every transaction that passes through our screening pipeline already stores:
- Sender and receiver account numbers (HMAC-hashed for privacy)
- Amount, currency, channel, timestamp
- Bank codes for external transfers
The graph is already there. We just needed to walk it.
The algorithm
TRACE(accountNumber, direction, depth, window):
1. Resolve the starting account's hash
2. BFS by hop (default 3, max 5):
- Find all transactions FROM this account
within `window` hours of the parent (default 72h)
- Each downstream account becomes a node
- Each transaction becomes an edge (amount, timestamp, external ID)
3. Propagate amounts: every node shows ₦X (Y% of the origin)
4. Auto-detect patterns:
- MULE_FAN_OUT: >=5 distinct receivers from one account
- PASS_THROUGH: forwards >=80% of inflow
- CASH_OUT: >=3 distinct senders converge into one account
5. Mark terminal accounts + receiving bank codes
6. Cap: 300 nodes, 1,500 edges
Each account is expanded exactly once. A node reached via five incoming edges must not fan out five times. That is a convergence-multiplication bug we caught in live testing and regression-tested.
The three patterns that sell it
When we demo this to fraud desks, the graph itself is impressive, but the auto-detected patterns are what make them lean forward:
- Mule distribution: the moment the stolen money splits into six accounts of ₦3.3M each, the graph shows a red "Mule distribution" badge on the splitter node
- Pass-through: every intermediate account that forwards nearly everything it receives gets tagged, so the investigator doesn't need to check each one manually
- Cash-out point: when multiple mules converge back into a single account for withdrawal, it is flagged as the consolidation point
Deterministic, not predictive: these are not ML predictions. They are deterministic graph properties: explainable, auditable, and always correct given the underlying data.
Exit points: the EFCC handoff
The trail doesn't go dark at the bank's boundary. When money leaves to another institution, the transaction carries the receiving bank's code. Terminal nodes in the graph are labeled with exited → bank 058 (GTBank) or exited → bank 033 (Sterling).
The report includes an "External Transfers" section listing every exit with the amount, receiving bank, account number, and timestamp. That is precisely what the EFCC needs to extend the trace formally.
The report
One click generates an EFCC/court-ready PDF:
- Reference number, prepared-by, generated-at
- Summary statistics (accounts, transfers, hops, origin amount)
- Detected patterns with account identifiers
- Complete fund trail table (hop-by-hop, with amounts, timestamps, external IDs)
- External transfers section for onward NIBSS tracing
- Methodology note tied to immutable screening records
Every trace is persisted and audited (INVESTIGATION_TRACE_GENERATED). The PDF regenerates from the stored snapshot, so it can never drift from what the investigator saw. This is investigative access to customer data; NDPA legitimacy requires a documented law-enforcement purpose.
The technology choice
We use ReactFlow for the interactive graph: pan, zoom, click any account for detail. The layout algorithm is dagre (left-to-right hierarchical), so converging flows curve naturally and deep chains stay readable.
The backend is pure TypeScript: a BFS algorithm with injected loaders, fully unit-testable. The service provides a Prisma-backed loader that queries transactions by HMAC-hashed account numbers. No graph database needed. PostgreSQL indexes on the hash columns are sufficient.
Why this matters
No global AML vendor (Actimize, Feedzai, ComplyAdvantage) localizes for EFCC workflows. This is a feature that exists because we sat with Nigerian fraud investigators and asked: "what takes you the longest?" The answer was fund tracing. Now it takes seconds.
See a live trace on your own data
We'll run the tracer against a scenario from your institution in a 30-minute demo: blocked transaction, full fund trace, frozen destination, packaged case.