AI Financial Fraud Detection System
Real-time transaction monitoring with AI-powered fraud detection and instant response
typescript
import { cronflow } from 'cronflow';
import { z } from 'zod';
// Types for better type safety
interface Transaction {
transactionId: string;
accountId: string;
cardId?: string;
amount: number;
currency: string;
merchantId: string;
merchantCategory: string;
timestamp: string;
location: {
country: string;
city: string;
coordinates?: {
lat: number;
lng: number;
};
};
paymentMethod: 'card' | 'digital_wallet' | 'bank_transfer';
channel: 'online' | 'pos' | 'atm' | 'mobile';
deviceFingerprint?: string;
ipAddress?: string;
}
interface RiskAssessment {
riskScore: number;
riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
riskFactors: string[];
confidence: number;
anomalyFlags: string[];
}
interface CardBlockResult {
blocked: boolean;
cardId: string;
reason: string;
timestamp: string;
blockId: string;
}
// Transaction data schema for validation
const TransactionSchema = z.object({
transactionId: z.string(),
accountId: z.string(),
cardId: z.string().optional(),
amount: z.number().positive(),
currency: z.string().length(3),
merchantId: z.string(),
merchantCategory: z.string(),
timestamp: z.string().datetime(),
location: z.object({
country: z.string(),
city: z.string(),
coordinates: z
.object({
lat: z.number(),
lng: z.number(),
})
.optional(),
}),
paymentMethod: z.enum(['card', 'digital_wallet', 'bank_transfer']),
channel: z.enum(['online', 'pos', 'atm', 'mobile']),
deviceFingerprint: z.string().optional(),
ipAddress: z.string().optional(),
});
// Risk assessment result schema
const RiskAssessmentSchema = z.object({
riskScore: z.number().min(0).max(100),
riskLevel: z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']),
riskFactors: z.array(z.string()),
confidence: z.number().min(0).max(1),
anomalyFlags: z.array(z.string()),
});
// AI/ML Mock Functions (replace with actual AI service calls)
async function analyzeTransactionBehavior(
transaction: Transaction,
userHistory: any[]
): Promise<RiskAssessment> {
// Simulate behavioral analysis
const riskFactors: string[] = [];
let riskScore = 0;
// Amount analysis
const avgAmount =
userHistory.reduce((sum, t) => sum + t.amount, 0) / userHistory.length;
if (transaction.amount > avgAmount * 3) {
riskFactors.push('unusual_amount');
riskScore += 25;
}
// Time pattern analysis
const hour = new Date(transaction.timestamp).getHours();
if (hour < 6 || hour > 22) {
riskFactors.push('unusual_time');
riskScore += 15;
}
// Location analysis
const lastTransaction = userHistory[0];
if (
lastTransaction &&
transaction.location.country !== lastTransaction.location.country
) {
riskFactors.push('unusual_location');
riskScore += 30;
}
// Frequency analysis
const recentTransactions = userHistory.filter(
t => new Date(t.timestamp) > new Date(Date.now() - 60 * 60 * 1000) // Last hour
);
if (recentTransactions.length > 5) {
riskFactors.push('high_frequency');
riskScore += 20;
}
return {
riskScore: Math.min(riskScore, 100),
riskLevel:
riskScore > 75
? 'CRITICAL'
: riskScore > 50
? 'HIGH'
: riskScore > 25
? 'MEDIUM'
: 'LOW',
riskFactors,
confidence: 0.85,
anomalyFlags: riskFactors,
};
}
async function performAnomalyDetection(transaction: Transaction): Promise<{
anomalies: string[];
anomalyScore: number;
detectionConfidence: number;
}> {
// Simulate ML-based anomaly detection
const anomalies: string[] = [];
// Merchant pattern analysis
if (
transaction.merchantCategory === 'gambling' &&
transaction.amount > 1000
) {
anomalies.push('high_value_gambling');
}
// Device fingerprint analysis
if (!transaction.deviceFingerprint) {
anomalies.push('missing_device_fingerprint');
}
// IP analysis
if (transaction.ipAddress && transaction.ipAddress.startsWith('10.0.0.')) {
anomalies.push('suspicious_ip_range');
}
return {
anomalies,
anomalyScore: anomalies.length * 15,
detectionConfidence: 0.92,
};
}
async function getUserTransactionHistory(accountId: string) {
// Simulate database query for user transaction history
// In production, this would query your transaction database
return [
{
transactionId: 'txn_001',
amount: 150.0,
timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),
location: { country: 'US', city: 'New York' },
merchantCategory: 'grocery',
},
{
transactionId: 'txn_002',
amount: 45.0,
timestamp: new Date(Date.now() - 4 * 60 * 60 * 1000).toISOString(),
location: { country: 'US', city: 'New York' },
merchantCategory: 'restaurant',
},
];
}
async function blockCard(
cardId: string,
reason: string
): Promise<CardBlockResult> {
// Simulate card blocking API call
console.log(`🚫 CARD BLOCKED: ${cardId} - Reason: ${reason}`);
return {
blocked: true,
cardId,
reason,
timestamp: new Date().toISOString(),
blockId: `block_${Date.now()}`,
};
}
async function sendFraudAlert(
transaction: Transaction,
riskAssessment: RiskAssessment
) {
// Simulate sending fraud alert to security team
console.log(
`🚨 FRAUD ALERT: Transaction ${transaction.transactionId} flagged as ${riskAssessment.riskLevel} risk`
);
return {
alertSent: true,
alertId: `alert_${Date.now()}`,
notificationChannels: ['email', 'slack', 'sms'],
timestamp: new Date().toISOString(),
};
}
async function notifyCustomer(
accountId: string,
transaction: Transaction,
action: string
) {
// Simulate customer notification
console.log(
`📱 Customer notification sent to account ${accountId}: ${action} for transaction ${transaction.transactionId}`
);
return {
notificationSent: true,
notificationId: `notify_${Date.now()}`,
channel: 'push_notification',
message: `Security alert: ${action} for transaction of ${transaction.currency} ${transaction.amount}`,
};
}
// Define the AI Financial Fraud Detection Workflow
const fraudDetectionWorkflow = cronflow.define({
id: 'ai-fraud-detection',
name: 'AI Financial Fraud Detection System',
description:
'Real-time transaction monitoring with AI-powered fraud detection and instant response',
hooks: {
onSuccess: (ctx, stepId) => {
if (!stepId) {
console.log('✅ Fraud detection workflow completed successfully');
console.log(
`📊 Final result: ${ctx.last.action} for transaction ${ctx.last.transactionId}`
);
}
},
onFailure: (ctx, stepId) => {
console.log(
`❌ Fraud detection failed at step ${stepId}:`,
ctx.step_error
);
// In production, you'd send alerts to ops team
},
},
});
// Main fraud detection workflow
fraudDetectionWorkflow
.onWebhook('/webhooks/transaction', {
schema: TransactionSchema,
method: 'POST',
})
// Step 1: Initial transaction validation and enrichment
.step('validate-and-enrich-transaction', async ctx => {
const transaction = ctx.payload;
console.log(
`🔍 Processing transaction ${transaction.transactionId} for ${transaction.currency} ${transaction.amount}`
);
// Enrich transaction with additional data
const enrichedTransaction = {
...transaction,
processedAt: new Date().toISOString(),
processingId: `proc_${Date.now()}`,
riskChecksRequired: true,
};
return {
transaction: enrichedTransaction,
validated: true,
enrichmentComplete: true,
};
})
// Step 2: Parallel processing - Behavioral analysis and anomaly detection
.parallel([
// Behavioral Analysis Branch
async ctx => {
const transaction = ctx.last.transaction;
const userHistory = await getUserTransactionHistory(
transaction.accountId
);
const behaviorAnalysis = await analyzeTransactionBehavior(
transaction,
userHistory
);
return {
type: 'behavioral_analysis',
result: behaviorAnalysis,
userHistoryCount: userHistory.length,
analysisTimestamp: new Date().toISOString(),
};
},
// Anomaly Detection Branch
async ctx => {
const transaction = ctx.last.transaction;
const anomalyResult = await performAnomalyDetection(transaction);
return {
type: 'anomaly_detection',
result: anomalyResult,
analysisTimestamp: new Date().toISOString(),
};
},
])
// Step 3: Risk score aggregation and decision making
.step('aggregate-risk-assessment', async ctx => {
const transaction =
ctx.steps['validate-and-enrich-transaction'].output.transaction;
const analyses = ctx.last;
// Find behavioral and anomaly analysis results
const behaviorAnalysis = analyses.find(
a => a.type === 'behavioral_analysis'
)?.result;
const anomalyAnalysis = analyses.find(
a => a.type === 'anomaly_detection'
)?.result;
// Aggregate risk scores
const totalRiskScore =
behaviorAnalysis.riskScore + anomalyAnalysis.anomalyScore;
const finalRiskScore = Math.min(totalRiskScore, 100);
// Determine final risk level
let finalRiskLevel = 'LOW';
if (finalRiskScore > 80) finalRiskLevel = 'CRITICAL';
else if (finalRiskScore > 60) finalRiskLevel = 'HIGH';
else if (finalRiskScore > 30) finalRiskLevel = 'MEDIUM';
// Combine all risk factors
const allRiskFactors = [
...behaviorAnalysis.riskFactors,
...anomalyAnalysis.anomalies,
];
const finalAssessment = {
transactionId: transaction.transactionId,
finalRiskScore,
finalRiskLevel,
allRiskFactors,
behaviorScore: behaviorAnalysis.riskScore,
anomalyScore: anomalyAnalysis.anomalyScore,
confidence:
(behaviorAnalysis.confidence + anomalyAnalysis.detectionConfidence) / 2,
assessmentTimestamp: new Date().toISOString(),
};
console.log(
`📊 Risk Assessment Complete: ${finalRiskLevel} (${finalRiskScore}/100) for transaction ${transaction.transactionId}`
);
return {
transaction,
assessment: finalAssessment,
requiresAction:
finalRiskLevel === 'CRITICAL' || finalRiskLevel === 'HIGH',
};
})
// Step 4: Conditional processing based on risk level
.if('is-high-risk', ctx => ctx.last.requiresAction)
// High Risk Branch - Immediate action required
.step('immediate-fraud-response', async ctx => {
const { transaction, assessment } = ctx.last;
console.log(
`🚨 HIGH RISK DETECTED: Taking immediate action for transaction ${transaction.transactionId}`
);
// For CRITICAL risk, block the card immediately
let cardBlocked: CardBlockResult | null = null;
if (assessment.finalRiskLevel === 'CRITICAL' && transaction.cardId) {
cardBlocked = await blockCard(
transaction.cardId,
`Critical fraud risk detected: ${assessment.allRiskFactors.join(', ')}`
);
}
// Send fraud alert to security team
const fraudAlert = await sendFraudAlert(transaction, assessment);
// Notify customer
const customerNotification = await notifyCustomer(
transaction.accountId,
transaction,
cardBlocked
? 'Card blocked due to suspicious activity'
: 'Transaction flagged for review'
);
return {
transactionId: transaction.transactionId,
action: cardBlocked ? 'CARD_BLOCKED' : 'FLAGGED_FOR_REVIEW',
cardBlocked,
fraudAlert,
customerNotification,
responseTime: new Date().toISOString(),
};
})
// Human in the loop for HIGH risk (not CRITICAL)
.if(
'requires-human-review',
ctx =>
ctx.last.assessment.finalRiskLevel === 'HIGH' && !ctx.last.cardBlocked
)
.humanInTheLoop({
timeout: '15m',
description: 'High-risk transaction requires manual review',
onPause: (ctx, token) => {
const transaction = ctx.last.transaction;
console.log(
`⏸️ Human review required for transaction ${transaction.transactionId}`
);
console.log(`🔑 Review token: ${token}`);
console.log(`💰 Amount: ${transaction.currency} ${transaction.amount}`);
console.log(`📊 Risk Score: ${ctx.last.assessment.finalRiskScore}/100`);
console.log(
`⚠️ Risk Factors: ${ctx.last.assessment.allRiskFactors.join(', ')}`
);
// In production, send this to your fraud review team via email/Slack
},
})
.step('process-human-decision', async ctx => {
const { transaction, assessment } =
ctx.steps['aggregate-risk-assessment'].output;
if (ctx.last.timedOut) {
// Auto-approve if no human response within timeout
console.log(
`⏰ Review timeout - Auto-approving transaction ${transaction.transactionId}`
);
return {
transactionId: transaction.transactionId,
action: 'AUTO_APPROVED',
reason: 'Human review timeout',
timestamp: new Date().toISOString(),
};
}
const decision = ctx.last.approved ? 'APPROVED' : 'BLOCKED';
console.log(
`👤 Human decision: ${decision} for transaction ${transaction.transactionId}`
);
// If blocked by human, block the card
let cardBlocked: CardBlockResult | null = null;
if (!ctx.last.approved && transaction.cardId) {
cardBlocked = await blockCard(
transaction.cardId,
`Blocked by fraud analyst: ${ctx.last.reason || 'Manual review'}`
);
}
// Notify customer of decision
const customerNotification = await notifyCustomer(
transaction.accountId,
transaction,
ctx.last.approved
? 'Transaction approved after review'
: 'Transaction blocked after review'
);
return {
transactionId: transaction.transactionId,
action: decision,
reason: ctx.last.reason,
reviewedBy: 'human_analyst',
cardBlocked,
customerNotification,
timestamp: new Date().toISOString(),
};
})
.endIf()
.endIf()
// Step 5: Low/Medium risk processing
.if('is-low-medium-risk', ctx => !ctx.last.requiresAction)
.step('standard-processing', async ctx => {
const { transaction, assessment } = ctx.last;
console.log(
`✅ Transaction ${transaction.transactionId} approved - ${assessment.finalRiskLevel} risk (${assessment.finalRiskScore}/100)`
);
// Log for audit trail
return {
transactionId: transaction.transactionId,
action: 'APPROVED',
riskLevel: assessment.finalRiskLevel,
riskScore: assessment.finalRiskScore,
timestamp: new Date().toISOString(),
processingTime: Date.now() - new Date(transaction.processedAt).getTime(),
};
})
.endIf()
// Step 6: Final audit logging and metrics
.step('audit-and-metrics', async ctx => {
const transaction =
ctx.steps['aggregate-risk-assessment'].output.transaction;
const assessment = ctx.steps['aggregate-risk-assessment'].output.assessment;
// Determine final action taken
let finalAction = 'APPROVED';
let actionDetails = {};
if (ctx.steps['immediate-fraud-response']?.output) {
finalAction = ctx.steps['immediate-fraud-response'].output.action;
actionDetails = ctx.steps['immediate-fraud-response'].output;
} else if (ctx.steps['process-human-decision']?.output) {
finalAction = ctx.steps['process-human-decision'].output.action;
actionDetails = ctx.steps['process-human-decision'].output;
} else if (ctx.steps['standard-processing']?.output) {
finalAction = ctx.steps['standard-processing'].output.action;
actionDetails = ctx.steps['standard-processing'].output;
}
// Calculate total processing time
const processingTime =
Date.now() - new Date(transaction.processedAt).getTime();
// Audit log
const auditRecord = {
transactionId: transaction.transactionId,
accountId: transaction.accountId,
amount: transaction.amount,
currency: transaction.currency,
finalAction,
riskScore: assessment.finalRiskScore,
riskLevel: assessment.finalRiskLevel,
riskFactors: assessment.allRiskFactors,
processingTimeMs: processingTime,
timestamp: new Date().toISOString(),
workflowId: 'ai-fraud-detection',
actionDetails,
};
console.log(
`📋 Audit record created for transaction ${transaction.transactionId}`
);
console.log(`⚡ Processing completed in ${processingTime}ms`);
// In production, store this in your audit database
// await storeAuditRecord(auditRecord);
// Update metrics (in production, send to monitoring system)
// await updateFraudDetectionMetrics({
// transactionProcessed: 1,
// riskLevel: assessment.finalRiskLevel,
// action: finalAction,
// processingTime: processingTime
// });
return {
auditComplete: true,
transactionId: transaction.transactionId,
finalAction,
processingTimeMs: processingTime,
workflowCompleted: true,
};
})
// Background action - doesn't block workflow completion
.action('background-notifications', async ctx => {
// Send background notifications to various systems
console.log('📤 Sending background notifications to compliance systems...');
// Example: Update external fraud monitoring systems
// await notifyExternalFraudSystems(ctx.last);
// Example: Update customer risk profile
// await updateCustomerRiskProfile(ctx.last);
return { backgroundNotificationsSent: true };
});
// Performance monitoring workflow (separate workflow for system health)
const performanceMonitoringWorkflow = cronflow.define({
id: 'fraud-detection-monitoring',
name: 'Fraud Detection Performance Monitoring',
description: 'Monitor system performance and throughput metrics',
});
performanceMonitoringWorkflow
.onWebhook('/webhooks/performance-metrics', {
method: 'POST',
schema: z.object({
timeWindow: z.string().optional().default('1h'),
includeDetailedMetrics: z.boolean().optional().default(false),
}),
})
.step('collect-metrics', async ctx => {
// Simulate collecting performance metrics
const metrics = {
transactionsProcessed: Math.floor(Math.random() * 10000) + 5000,
averageProcessingTime: Math.floor(Math.random() * 50) + 10, // ms
fraudDetectionRate: (Math.random() * 5 + 0.5).toFixed(2), // %
falsePositiveRate: (Math.random() * 2 + 0.1).toFixed(2), // %
systemThroughput: Math.floor(Math.random() * 500) + 100, // transactions/second
uptime: '99.98%',
timestamp: new Date().toISOString(),
};
console.log('📊 System Performance Metrics:');
console.log(` Transactions Processed: ${metrics.transactionsProcessed}`);
console.log(` Avg Processing Time: ${metrics.averageProcessingTime}ms`);
console.log(` Fraud Detection Rate: ${metrics.fraudDetectionRate}%`);
console.log(` False Positive Rate: ${metrics.falsePositiveRate}%`);
console.log(` System Throughput: ${metrics.systemThroughput} tx/sec`);
return metrics;
});
// Export for use
export { fraudDetectionWorkflow, performanceMonitoringWorkflow };
// Example usage:
console.log('🚀 Starting AI Financial Fraud Detection System...');
// In your main application file, you would start the workflows:
// cronflow.start();
/*
USAGE EXAMPLES:
1. Test the fraud detection with a sample transaction:
curl -X POST http://localhost:3000/webhooks/transaction \
-H "Content-Type: application/json" \
-d '{
"transactionId": "txn_12345",
"accountId": "acc_67890",
"cardId": "card_11111",
"amount": 5000.00,
"currency": "USD",
"merchantId": "merchant_999",
"merchantCategory": "gambling",
"timestamp": "2025-01-27T22:30:00Z",
"location": {
"country": "RU",
"city": "Moscow"
},
"paymentMethod": "card",
"channel": "online",
"ipAddress": "10.0.0.1"
}'
2. Resume a paused workflow (for human review):
// Approve transaction
await cronflow.resume('approval_token_123', {
approved: true,
reason: 'Verified with customer via phone'
});
// Reject transaction
await cronflow.resume('approval_token_123', {
approved: false,
reason: 'Confirmed fraudulent activity'
});
3. Check performance metrics:
curl -X POST http://localhost:3000/webhooks/performance-metrics \
-H "Content-Type: application/json" \
-d '{"timeWindow": "1h", "includeDetailedMetrics": true}'
FEATURES IMPLEMENTED:
✅ Real-time transaction monitoring via webhooks
✅ AI-powered behavioral analysis and anomaly detection
✅ Parallel processing for maximum throughput (microsecond latency)
✅ Dynamic risk scoring with multiple factors
✅ Instant card blocking for critical threats
✅ Human-in-the-loop for complex cases with timeout
✅ Customer notifications and fraud alerts
✅ Comprehensive audit logging
✅ Background processing for non-blocking operations
✅ Performance monitoring and metrics
✅ Type-safe schema validation with Zod
✅ Error handling and workflow hooks
✅ Conditional logic based on risk levels
✅ Support for thousands of transactions per second
KILLER FEATURE:
The workflow processes transactions in parallel streams with microsecond
inter-step latency, enabling analysis of thousands of transactions per
second while maintaining real-time fraud detection capabilities.
*/