Use Cases
Fintech Platform
Build a complete financial services platform with Business-as-Code
Build a complete, autonomous financial services platform using Business-as-Code principles.
Overview
This use case demonstrates building a fintech platform that:
- Manages customer accounts securely
- Processes transactions in real-time
- Handles KYC/AML compliance automatically
- Detects fraud using AI
- Processes payments through multiple channels
- Manages reconciliation workflows
- Generates regulatory reports
- Provides financial insights and analytics
Architecture
graph TB
subgraph Frontend["User Experience"]
WebApp[Web Application]
MobileApp[Mobile App]
API[REST/GraphQL API]
end
subgraph Core["Core Banking"]
Accounts[Account Management]
Ledger[General Ledger]
Transactions[Transaction Engine]
Balance[Balance Management]
end
subgraph Processing["Payment Processing"]
PaymentGateway[Payment Gateway]
ACH[ACH Processing]
Wire[Wire Transfers]
Cards[Card Processing]
end
subgraph Compliance["Compliance & Risk"]
KYC[KYC Verification]
AML[AML Screening]
Fraud[Fraud Detection]
Risk[Risk Assessment]
end
subgraph AI["AI Services"]
FraudAI[Fraud Detection AI]
RiskAI[Risk Scoring AI]
InsightsAI[Financial Insights]
SupportAI[Customer Support AI]
end
subgraph Integration["External Systems"]
Plaid[Plaid/Banking APIs]
Stripe[Payment Providers]
Identity[Identity Verification]
Reporting[Regulatory Reporting]
end
WebApp --> API
MobileApp --> API
API --> Accounts
Accounts --> Ledger
Accounts --> Transactions
Transactions --> Balance
Transactions --> PaymentGateway
PaymentGateway --> ACH
PaymentGateway --> Wire
PaymentGateway --> Cards
Accounts --> KYC
Transactions --> AML
Transactions --> Fraud
Accounts --> Risk
Fraud -.->|AI| FraudAI
Risk -.->|AI| RiskAI
Accounts -.->|AI| InsightsAI
KYC --> Identity
PaymentGateway --> Stripe
Accounts --> Plaid
Compliance --> Reporting
Core Entities
Financial Accounts
import $, { db, on, send, ai } from 'sdk.do'
// Create bank account
const account = await $.BankAccount.create({
$type: 'BankAccount',
// Account details
accountNumber: generateAccountNumber(),
accountType: 'checking',
bankAccountType: 'DepositAccount',
// Ownership
accountHolder: customer,
// Balance
accountBalance: {
$type: 'MonetaryAmount',
value: 0,
currency: 'USD',
},
availableBalance: {
$type: 'MonetaryAmount',
value: 0,
currency: 'USD',
},
// Limits
dailyTransactionLimit: 5000,
monthlyTransactionLimit: 50000,
// Interest
interestRate: 0.01,
interestCompoundingFrequency: 'monthly',
// Status
accountStatus: 'active',
openedDate: new Date(),
// Metadata
createdAt: new Date(),
})
await db.relate(customer, $.owns, account)Transactions
// Financial transaction
const transaction = await $.FinancialTransaction.create({
$type: 'FinancialTransaction',
// Transaction details
identifier: `TXN-${Date.now()}`,
transactionType: 'Transfer',
// Parties
sender: fromAccount,
recipient: toAccount,
// Amount
amount: {
$type: 'MonetaryAmount',
value: 100.0,
currency: 'USD',
},
// Fees
transactionFee: {
$type: 'MonetaryAmount',
value: 0.5,
currency: 'USD',
},
// Status
transactionStatus: 'pending',
// Timestamps
transactionDate: new Date(),
settledDate: null,
// Metadata
description: 'Payment for invoice #12345',
metadata: {
invoiceId: '12345',
category: 'business',
},
})Business Functions
1. Account Opening & KYC
Complete account opening with automated KYC/AML verification.
// Account opening workflow
async function openAccount(params: { customer: Person | Organization; accountType: 'checking' | 'savings' | 'business'; initialDeposit?: number }) {
const { customer, accountType, initialDeposit } = params
// Step 1: Verify identity (KYC)
const kycResult = await verifyIdentity(customer)
if (!kycResult.verified) {
throw new Error(`KYC verification failed: ${kycResult.reason}`)
}
// Step 2: AML screening
const amlResult = await screenAML(customer)
if (amlResult.risk === 'high') {
// Flag for manual review
await send($.Review.required, {
customer,
reason: 'high-risk-aml',
details: amlResult,
})
throw new Error('Account requires manual review')
}
// Step 3: Risk assessment
const riskScore = await ai.analyze('customer-risk', {
customer,
kyc: kycResult,
aml: amlResult,
accountType,
})
// Step 4: Create account
const account = await $.BankAccount.create({
$type: 'BankAccount',
accountNumber: generateAccountNumber(),
routingNumber: getRoutingNumber(),
accountType,
accountHolder: customer,
// Initial balance
accountBalance: {
$type: 'MonetaryAmount',
value: initialDeposit || 0,
currency: 'USD',
},
availableBalance: {
$type: 'MonetaryAmount',
value: initialDeposit || 0,
currency: 'USD',
},
// Limits based on risk
dailyTransactionLimit: riskScore.limits.daily,
monthlyTransactionLimit: riskScore.limits.monthly,
// Compliance
kycVerified: true,
kycVerifiedAt: new Date(),
kycProvider: kycResult.provider,
riskLevel: riskScore.level,
// Status
accountStatus: 'active',
openedDate: new Date(),
})
await db.relate(customer, $.owns, account)
// Step 5: Create general ledger entries
if (initialDeposit > 0) {
await createLedgerEntry({
account: account.$id,
type: 'credit',
amount: initialDeposit,
description: 'Initial deposit',
category: 'deposit',
})
}
// Step 6: Send welcome materials
await send($.Email.send, {
to: customer.email,
template: 'account-opened',
data: {
account,
accountNumber: account.accountNumber,
routingNumber: account.routingNumber,
},
})
// Step 7: Set up fraud monitoring
await send($.Monitoring.enable, {
account,
rules: riskScore.monitoringRules,
})
await send($.Account.opened, account)
return account
}
// KYC verification
async function verifyIdentity(customer: Person | Organization) {
const isOrganization = customer.$type === 'Organization'
if (isOrganization) {
// Business verification
return await verifyBusiness(customer as Organization)
}
// Individual verification
const person = customer as Person
// Call identity verification service
const verification = await send($.Identity.verify, {
firstName: person.givenName,
lastName: person.familyName,
dateOfBirth: person.birthDate,
ssn: person.taxID,
address: person.address,
phone: person.telephone,
email: person.email,
// Document verification
documents: [
{
type: 'government_id',
number: person.identifier,
expirationDate: person.identifierExpiration,
},
],
})
// Save verification result
await db.update($.Person, person.$id, {
kycStatus: verification.status,
kycVerifiedAt: verification.verified ? new Date() : null,
kycProvider: 'veriff',
kycReferenceId: verification.id,
})
return {
verified: verification.status === 'approved',
status: verification.status,
reason: verification.reason,
provider: 'veriff',
timestamp: new Date(),
}
}
// AML screening
async function screenAML(customer: Person | Organization) {
// Check sanctions lists
const sanctionsCheck = await send($.AML.checkSanctions, {
name: customer.name,
address: customer.address,
dateOfBirth: customer.birthDate,
})
// Check PEP (Politically Exposed Person) lists
const pepCheck = await send($.AML.checkPEP, {
name: customer.name,
})
// Check adverse media
const mediaCheck = await ai.analyze('adverse-media', {
name: customer.name,
sources: ['news', 'legal', 'regulatory'],
})
// Calculate risk score
const riskScore = calculateAMLRisk({
sanctions: sanctionsCheck,
pep: pepCheck,
media: mediaCheck,
})
// Save screening result
await db.create($.AMLScreening, {
customer: customer.$id,
screenedAt: new Date(),
sanctionsMatch: sanctionsCheck.matches.length > 0,
pepMatch: pepCheck.matches.length > 0,
adverseMedia: mediaCheck.findings.length > 0,
riskScore: riskScore.score,
riskLevel: riskScore.level,
status: riskScore.level === 'high' ? 'flagged' : 'cleared',
})
return {
risk: riskScore.level,
score: riskScore.score,
findings: {
sanctions: sanctionsCheck.matches,
pep: pepCheck.matches,
media: mediaCheck.findings,
},
}
}2. Transaction Processing
Real-time transaction processing with validation and authorization.
// Process transaction
async function processTransaction(params: { fromAccount: BankAccount; toAccount: BankAccount; amount: number; description?: string; metadata?: any }) {
const { fromAccount, toAccount, amount, description, metadata } = params
// Create transaction record
const transaction = await $.FinancialTransaction.create({
$type: 'FinancialTransaction',
identifier: `TXN-${Date.now()}`,
transactionType: 'Transfer',
sender: fromAccount,
recipient: toAccount,
amount: {
$type: 'MonetaryAmount',
value: amount,
currency: 'USD',
},
transactionStatus: 'pending',
transactionDate: new Date(),
description,
metadata,
})
await send($.Transaction.created, transaction)
return transaction
}
// Transaction validation
on($.Transaction.created, async (transaction) => {
try {
// Step 1: Validate accounts
const fromAccount = transaction.sender
const toAccount = transaction.recipient
if (fromAccount.accountStatus !== 'active') {
throw new Error('Sender account is not active')
}
if (toAccount.accountStatus !== 'active') {
throw new Error('Recipient account is not active')
}
// Step 2: Check available balance
const amount = transaction.amount.value
const fee = calculateTransactionFee(transaction)
const totalAmount = amount + fee
if (fromAccount.availableBalance.value < totalAmount) {
throw new Error('Insufficient funds')
}
// Step 3: Check transaction limits
const dailyTotal = await getDailyTransactionTotal(fromAccount)
if (dailyTotal + amount > fromAccount.dailyTransactionLimit) {
throw new Error('Daily transaction limit exceeded')
}
// Step 4: Fraud detection
const fraudCheck = await ai.analyze('fraud-detection', {
transaction,
account: fromAccount,
history: await getTransactionHistory(fromAccount, '30d'),
patterns: await getCustomerBehavior(fromAccount.accountHolder),
})
if (fraudCheck.risk === 'high' && fraudCheck.confidence > 0.8) {
// Block transaction and alert
await db.update($.FinancialTransaction, transaction.$id, {
transactionStatus: 'blocked',
blockReason: 'fraud-suspected',
})
await send($.Fraud.detected, {
transaction,
fraudCheck,
})
throw new Error('Transaction blocked: fraud suspected')
}
if (fraudCheck.risk === 'medium' && fraudCheck.confidence > 0.7) {
// Require additional verification
await db.update($.FinancialTransaction, transaction.$id, {
transactionStatus: 'verification-required',
})
await send($.Transaction.requiresVerification, {
transaction,
reason: fraudCheck.reason,
})
return
}
// Step 5: Reserve funds
await db.update($.BankAccount, fromAccount.$id, {
'availableBalance.value': fromAccount.availableBalance.value - totalAmount,
})
// Step 6: Process transaction
await send($.Transaction.process, transaction)
} catch (error) {
// Update transaction status
await db.update($.FinancialTransaction, transaction.$id, {
transactionStatus: 'failed',
failureReason: error.message,
})
await send($.Transaction.failed, {
transaction,
error: error.message,
})
throw error
}
})
// Execute transaction
on($.Transaction.process, async (transaction) => {
const fromAccount = transaction.sender
const toAccount = transaction.recipient
const amount = transaction.amount.value
const fee = calculateTransactionFee(transaction)
// Create ledger entries
const timestamp = new Date()
// Debit from sender
await createLedgerEntry({
account: fromAccount.$id,
transaction: transaction.$id,
type: 'debit',
amount: amount + fee,
description: transaction.description,
timestamp,
})
// Update sender balance
await db.update($.BankAccount, fromAccount.$id, {
'accountBalance.value': fromAccount.accountBalance.value - amount - fee,
})
// Credit to recipient
await createLedgerEntry({
account: toAccount.$id,
transaction: transaction.$id,
type: 'credit',
amount,
description: transaction.description,
timestamp,
})
// Update recipient balance
await db.update($.BankAccount, toAccount.$id, {
'accountBalance.value': toAccount.accountBalance.value + amount,
'availableBalance.value': toAccount.availableBalance.value + amount,
})
// Record fee revenue
if (fee > 0) {
await createLedgerEntry({
account: 'revenue',
transaction: transaction.$id,
type: 'credit',
amount: fee,
description: 'Transaction fee',
category: 'fee-income',
timestamp,
})
}
// Update transaction
await db.update($.FinancialTransaction, transaction.$id, {
transactionStatus: 'completed',
settledDate: timestamp,
transactionFee: {
$type: 'MonetaryAmount',
value: fee,
currency: 'USD',
},
})
await send($.Transaction.completed, transaction)
// Send notifications
await send($.Notification.send, {
to: fromAccount.accountHolder,
type: 'transaction',
message: `Payment sent: $${amount.toFixed(2)}`,
data: { transaction },
})
await send($.Notification.send, {
to: toAccount.accountHolder,
type: 'transaction',
message: `Payment received: $${amount.toFixed(2)}`,
data: { transaction },
})
})3. Fraud Detection
AI-powered real-time fraud detection and prevention.
// Fraud detection engine
async function detectFraud(transaction: FinancialTransaction) {
const account = transaction.sender
// Gather context
const context = {
transaction,
account,
// Transaction patterns
history: await getTransactionHistory(account, '90d'),
frequency: await getTransactionFrequency(account),
typicalAmount: await getTypicalTransactionAmount(account),
// Account patterns
accountAge: differenceInDays(new Date(), account.openedDate),
averageBalance: await getAverageBalance(account),
// Behavioral patterns
typicalTime: await getTypicalTransactionTime(account),
typicalRecipients: await getFrequentRecipients(account),
deviceFingerprint: transaction.metadata?.deviceFingerprint,
ipAddress: transaction.metadata?.ipAddress,
location: transaction.metadata?.location,
// External signals
velocityCheck: await checkTransactionVelocity(account),
blacklist: await checkBlacklist(transaction.recipient),
}
// AI fraud detection
const analysis = await ai.analyze('fraud-detection', context)
// Rule-based checks
const rules = [
// Amount anomaly
{
check: transaction.amount.value > context.typicalAmount * 5,
risk: 'high',
reason: 'Amount significantly higher than typical',
},
// Velocity check
{
check: context.velocityCheck.count > 10,
risk: 'high',
reason: 'Too many transactions in short period',
},
// New account
{
check: context.accountAge < 7,
risk: 'medium',
reason: 'New account (less than 7 days old)',
},
// Time anomaly
{
check: isUnusualTime(new Date(), context.typicalTime),
risk: 'medium',
reason: 'Transaction at unusual time',
},
// Location anomaly
{
check: transaction.metadata?.location && isUnusualLocation(transaction.metadata.location, account),
risk: 'high',
reason: 'Transaction from unusual location',
},
// Blacklisted recipient
{
check: context.blacklist.isListed,
risk: 'high',
reason: 'Recipient on fraud blacklist',
},
]
// Evaluate rules
const triggeredRules = rules.filter((rule) => rule.check)
const maxRisk = triggeredRules.reduce((max, rule) => {
const riskLevel = { low: 1, medium: 2, high: 3 }
return Math.max(max, riskLevel[rule.risk])
}, 0)
const riskLevels = ['none', 'low', 'medium', 'high']
const ruleBasedRisk = riskLevels[maxRisk]
// Combine AI and rule-based detection
const finalRisk = combineRiskScores(analysis.risk, ruleBasedRisk)
return {
risk: finalRisk,
confidence: analysis.confidence,
reason: [...triggeredRules.map((r) => r.reason), ...analysis.reasons],
score: analysis.score,
analysis,
}
}
// Handle fraud detection
on($.Fraud.detected, async ({ transaction, fraudCheck }) => {
// Log fraud event
await db.create($.FraudEvent, {
transaction: transaction.$id,
account: transaction.sender.$id,
riskLevel: fraudCheck.risk,
confidence: fraudCheck.confidence,
reasons: fraudCheck.reason,
detectedAt: new Date(),
status: 'pending-review',
})
// Block account temporarily
await db.update($.BankAccount, transaction.sender.$id, {
accountStatus: 'frozen',
frozenAt: new Date(),
frozenReason: 'fraud-suspected',
})
// Alert customer
await send($.Email.send, {
to: transaction.sender.accountHolder.email,
template: 'fraud-alert',
priority: 'urgent',
data: {
transaction,
reason: 'Suspicious activity detected on your account',
action: 'verify',
},
})
await send($.SMS.send, {
to: transaction.sender.accountHolder.telephone,
message: `FRAUD ALERT: Suspicious transaction detected. Please verify immediately: ${process.env.APP_URL}/verify/${transaction.$id}`,
})
// Alert fraud team
await send($.Notification.send, {
to: $.Role.FraudAnalyst,
priority: 'urgent',
message: `High-risk transaction detected: ${transaction.identifier}`,
action: { review: transaction.$id },
})
// Create case for investigation
await $.Case.create({
$type: 'Case',
identifier: `FRAUD-${Date.now()}`,
caseType: 'fraud-investigation',
subject: transaction.$id,
priority: 'high',
status: 'open',
assignedTo: await getAvailableFraudAnalyst(),
createdAt: new Date(),
})
})4. Payment Processing
Multi-channel payment processing with reconciliation.
// Process ACH payment
async function processACH(params: {
fromAccount: BankAccount
toAccount: { routingNumber: string; accountNumber: string }
amount: number
description?: string
}) {
const { fromAccount, toAccount, amount, description } = params
// Create ACH transaction
const achTransaction = await $.PaymentAction.create({
$type: 'PaymentAction',
identifier: `ACH-${Date.now()}`,
// Parties
agent: fromAccount.accountHolder,
recipient: toAccount,
// Amount
amount: {
$type: 'MonetaryAmount',
value: amount,
currency: 'USD',
},
// Payment method
paymentMethod: {
$type: 'PaymentMethod',
name: 'ACH',
},
// Status
actionStatus: 'pending',
// Metadata
description,
expectedSettlement: addBusinessDays(new Date(), 2),
createdAt: new Date(),
})
// Submit to ACH processor
await send($.ACH.submit, {
transaction: achTransaction,
fromRouting: fromAccount.routingNumber,
fromAccount: fromAccount.accountNumber,
toRouting: toAccount.routingNumber,
toAccount: toAccount.accountNumber,
amount,
description,
})
await send($.Payment.submitted, achTransaction)
return achTransaction
}
// Handle ACH returns
on($.ACH.returned, async ({ transaction, returnCode, reason }) => {
// Update transaction status
await db.update($.PaymentAction, transaction.$id, {
actionStatus: 'failed',
error: {
code: returnCode,
message: reason,
},
})
// Reverse transaction if already settled
if (transaction.actionStatus === 'completed') {
await send($.Transaction.reverse, {
original: transaction,
reason: 'ach-return',
})
}
// Notify customer
const account = await db.related(transaction, $.origin, $.BankAccount).then((accounts) => accounts[0])
await send($.Email.send, {
to: account.accountHolder.email,
template: 'payment-returned',
data: {
transaction,
returnCode,
reason,
},
})
})
// Wire transfer processing
async function processWire(params: {
fromAccount: BankAccount
toAccount: {
bankName: string
routingNumber: string
accountNumber: string
swiftCode?: string
beneficiaryName: string
beneficiaryAddress: string
}
amount: number
description?: string
}) {
const { fromAccount, toAccount, amount, description } = params
// Wire fee
const wireFee = amount > 10000 ? 0 : 25
// Check balance including fee
if (fromAccount.availableBalance.value < amount + wireFee) {
throw new Error('Insufficient funds (including wire fee)')
}
// Create wire transaction
const wireTransaction = await $.WireTransfer.create({
$type: 'WireTransfer',
identifier: `WIRE-${Date.now()}`,
// Parties
sender: fromAccount,
beneficiary: toAccount,
// Amount
amount: {
$type: 'MonetaryAmount',
value: amount,
currency: 'USD',
},
fee: {
$type: 'MonetaryAmount',
value: wireFee,
currency: 'USD',
},
// Status
status: 'pending-approval',
// Wire details
wireType: toAccount.swiftCode ? 'international' : 'domestic',
description,
// Expected settlement
expectedSettlement: addBusinessDays(new Date(), 1),
createdAt: new Date(),
})
// Large wire transfers require approval
if (amount > 50000) {
await send($.Wire.requiresApproval, {
transaction: wireTransaction,
approver: $.Role.TreasuryManager,
})
} else {
await send($.Wire.submit, wireTransaction)
}
return wireTransaction
}
// Card payment processing
async function processCardPayment(params: { cardNumber: string; expiry: string; cvv: string; amount: number; description?: string; merchant: Organization }) {
const { cardNumber, expiry, cvv, amount, description, merchant } = params
// Tokenize card
const cardToken = await send($.Card.tokenize, {
cardNumber,
expiry,
cvv,
})
// Create payment
const payment = await $.PaymentAction.create({
$type: 'PaymentAction',
identifier: `CARD-${Date.now()}`,
// Amount
amount: {
$type: 'MonetaryAmount',
value: amount,
currency: 'USD',
},
// Payment method
paymentMethod: {
$type: 'CreditCard',
token: cardToken,
},
// Merchant
recipient: merchant,
// Status
actionStatus: 'pending',
description,
createdAt: new Date(),
})
// Submit to payment processor
const result = await send($.PaymentProcessor.charge, {
token: cardToken,
amount,
currency: 'USD',
description,
merchant: merchant.$id,
})
// Update payment
await db.update($.PaymentAction, payment.$id, {
actionStatus: result.status,
processorResponse: result,
})
if (result.status === 'succeeded') {
await send($.Payment.succeeded, payment)
} else {
await send($.Payment.failed, {
payment,
error: result.error,
})
}
return payment
}5. Reconciliation
Automated transaction reconciliation and settlement.
// Daily reconciliation process
async function runDailyReconciliation(date: Date) {
const startOfDay = startOfBusinessDay(date)
const endOfDay = endOfBusinessDay(date)
// Get all transactions for the day
const transactions = await db.list($.FinancialTransaction, {
where: {
transactionDate: {
$gte: startOfDay,
$lte: endOfDay,
},
transactionStatus: 'completed',
},
})
// Get ledger entries
const ledgerEntries = await db.list($.LedgerEntry, {
where: {
timestamp: {
$gte: startOfDay,
$lte: endOfDay,
},
},
})
// Calculate totals
const transactionTotals = transactions.reduce(
(acc, txn) => {
acc.count++
acc.credits += txn.amount.value
acc.debits += txn.amount.value + (txn.transactionFee?.value || 0)
acc.fees += txn.transactionFee?.value || 0
return acc
},
{ count: 0, credits: 0, debits: 0, fees: 0 }
)
const ledgerTotals = ledgerEntries.reduce(
(acc, entry) => {
if (entry.type === 'credit') {
acc.credits += entry.amount
} else {
acc.debits += entry.amount
}
return acc
},
{ credits: 0, debits: 0 }
)
// Check if balanced
const isBalanced = Math.abs(transactionTotals.credits - ledgerTotals.credits) < 0.01 && Math.abs(transactionTotals.debits - ledgerTotals.debits) < 0.01
// Create reconciliation report
const reconciliation = await $.ReconciliationReport.create({
$type: 'Report',
name: `Daily Reconciliation - ${date.toISOString().split('T')[0]}`,
// Period
datePublished: new Date(),
reportPeriod: {
startDate: startOfDay,
endDate: endOfDay,
},
// Results
isBalanced,
transactions: transactionTotals,
ledger: ledgerTotals,
discrepancies: isBalanced ? [] : findDiscrepancies(transactions, ledgerEntries),
// Status
status: isBalanced ? 'balanced' : 'discrepancy',
})
if (!isBalanced) {
// Alert finance team
await send($.Alert.send, {
to: $.Role.FinanceTeam,
priority: 'high',
message: 'Daily reconciliation discrepancy detected',
data: { reconciliation },
})
}
await send($.Reconciliation.completed, reconciliation)
return reconciliation
}
// Bank statement reconciliation
async function reconcileBankStatement(params: { account: BankAccount; statement: BankStatement }) {
const { account, statement } = params
// Get internal transactions
const internalTransactions = await db.list($.FinancialTransaction, {
where: {
$or: [{ sender: account.$id }, { recipient: account.$id }],
transactionDate: {
$gte: statement.startDate,
$lte: statement.endDate,
},
},
})
// Match statement transactions with internal records
const matches = []
const unmatchedStatement = []
const unmatchedInternal = []
for (const statementTxn of statement.transactions) {
const match = internalTransactions.find(
(txn) => Math.abs(txn.amount.value - Math.abs(statementTxn.amount)) < 0.01 && isSameDay(txn.transactionDate, statementTxn.date)
)
if (match) {
matches.push({ statement: statementTxn, internal: match })
} else {
unmatchedStatement.push(statementTxn)
}
}
// Find unmatched internal transactions
for (const internalTxn of internalTransactions) {
const matched = matches.find((m) => m.internal.$id === internalTxn.$id)
if (!matched) {
unmatchedInternal.push(internalTxn)
}
}
// Create reconciliation report
const report = await $.ReconciliationReport.create({
$type: 'Report',
name: `Bank Statement Reconciliation - ${account.accountNumber}`,
account: account.$id,
statement: statement.$id,
matched: matches.length,
unmatchedStatement: unmatchedStatement.length,
unmatchedInternal: unmatchedInternal.length,
isReconciled: unmatchedStatement.length === 0 && unmatchedInternal.length === 0,
discrepancies: [
...unmatchedStatement.map((txn) => ({
type: 'statement-only',
transaction: txn,
})),
...unmatchedInternal.map((txn) => ({
type: 'internal-only',
transaction: txn,
})),
],
datePublished: new Date(),
})
return report
}6. Regulatory Compliance & Reporting
Automated compliance reporting for regulatory requirements.
// Generate SAR (Suspicious Activity Report)
async function generateSAR(params: { subject: Person | Organization; activity: string; transactions: FinancialTransaction[]; description: string }) {
const { subject, activity, transactions, description } = params
// Create SAR
const sar = await $.Report.create({
$type: 'Report',
name: 'Suspicious Activity Report',
// Subject information
subject: subject.$id,
subjectName: subject.name,
subjectType: subject.$type,
// Activity details
suspiciousActivity: activity,
description,
// Transactions
transactions: transactions.map((txn) => txn.$id),
totalAmount: transactions.reduce((sum, txn) => sum + txn.amount.value, 0),
// Dates
activityStartDate: transactions[0].transactionDate,
activityEndDate: transactions[transactions.length - 1].transactionDate,
reportDate: new Date(),
// Status
filedWith: 'FinCEN',
status: 'filed',
})
// Submit to FinCEN
await send($.FinCEN.submitSAR, sar)
// Log compliance action
await db.create($.ComplianceLog, {
action: 'sar-filed',
report: sar.$id,
filedBy: 'system',
filedAt: new Date(),
})
return sar
}
// CTR (Currency Transaction Report)
on($.Transaction.completed, async (transaction) => {
// File CTR for transactions over $10,000
if (transaction.amount.value > 10000) {
const ctr = await $.Report.create({
$type: 'Report',
name: 'Currency Transaction Report',
transaction: transaction.$id,
amount: transaction.amount.value,
// Parties
from: transaction.sender.accountHolder,
to: transaction.recipient.accountHolder,
// Filing
reportDate: new Date(),
filedWith: 'FinCEN',
status: 'pending',
})
await send($.FinCEN.submitCTR, ctr)
}
})
// OFAC screening
async function screenOFAC(entity: Person | Organization) {
// Check OFAC sanctions list
const result = await send($.OFAC.screen, {
name: entity.name,
address: entity.address,
dateOfBirth: entity.birthDate,
identification: entity.identifier,
})
// Save screening result
await db.create($.OFACScreening, {
entity: entity.$id,
screenedAt: new Date(),
matches: result.matches,
status: result.matches.length > 0 ? 'blocked' : 'cleared',
})
// Block if match found
if (result.matches.length > 0) {
await send($.Compliance.block, {
entity,
reason: 'ofac-match',
matches: result.matches,
})
}
return result
}
// Monthly compliance report
async function generateMonthlyComplianceReport(month: Date) {
const startDate = startOfMonth(month)
const endDate = endOfMonth(month)
// Gather compliance metrics
const metrics = {
// KYC
kycVerifications: await db.count($.Person, {
where: {
kycVerifiedAt: {
$gte: startDate,
$lte: endDate,
},
},
}),
// AML
amlScreenings: await db.count($.AMLScreening, {
where: {
screenedAt: {
$gte: startDate,
$lte: endDate,
},
},
}),
amlFlags: await db.count($.AMLScreening, {
where: {
screenedAt: {
$gte: startDate,
$lte: endDate,
},
status: 'flagged',
},
}),
// Fraud
fraudDetections: await db.count($.FraudEvent, {
where: {
detectedAt: {
$gte: startDate,
$lte: endDate,
},
},
}),
fraudBlocked: await db.count($.FraudEvent, {
where: {
detectedAt: {
$gte: startDate,
$lte: endDate,
},
status: 'confirmed',
},
}),
// Transactions
largeTransactions: await db.count($.FinancialTransaction, {
where: {
transactionDate: {
$gte: startDate,
$lte: endDate,
},
'amount.value': { $gt: 10000 },
},
}),
// Reports
sarsField: await db.count($.Report, {
where: {
reportDate: {
$gte: startDate,
$lte: endDate,
},
name: 'Suspicious Activity Report',
},
}),
ctrsFiled: await db.count($.Report, {
where: {
reportDate: {
$gte: startDate,
$lte: endDate,
},
name: 'Currency Transaction Report',
},
}),
}
// Create report
const report = await $.Report.create({
$type: 'Report',
name: `Monthly Compliance Report - ${month.toISOString().slice(0, 7)}`,
reportPeriod: {
startDate,
endDate,
},
metrics,
datePublished: new Date(),
status: 'final',
})
return report
}7. Financial Insights & Analytics
AI-powered financial insights for customers.
// Generate account insights
async function generateAccountInsights(account: BankAccount) {
// Gather transaction data
const transactions = await db.list($.FinancialTransaction, {
where: {
$or: [{ sender: account.$id }, { recipient: account.$id }],
transactionDate: {
$gte: subMonths(new Date(), 6),
},
},
})
// AI analysis
const insights = await ai.analyze('financial-insights', {
account,
transactions,
balance: account.accountBalance.value,
})
return {
// Spending patterns
spending: {
total: insights.spending.total,
average: insights.spending.average,
categories: insights.spending.byCategory,
trends: insights.spending.trends,
},
// Income
income: {
total: insights.income.total,
sources: insights.income.sources,
regularity: insights.income.regularity,
},
// Savings
savings: {
rate: insights.savings.rate,
trend: insights.savings.trend,
projection: insights.savings.projection,
},
// Recommendations
recommendations: insights.recommendations,
// Alerts
alerts: insights.alerts,
generatedAt: new Date(),
}
}
// Budget tracking
async function trackBudget(params: { account: BankAccount; budget: Budget; period: 'monthly' | 'weekly' }) {
const { account, budget, period } = params
const startDate = period === 'monthly' ? startOfMonth(new Date()) : startOfWeek(new Date())
// Get spending by category
const transactions = await db.list($.FinancialTransaction, {
where: {
sender: account.$id,
transactionDate: { $gte: startDate },
},
})
const spendingByCategory = transactions.reduce((acc, txn) => {
const category = txn.metadata?.category || 'uncategorized'
acc[category] = (acc[category] || 0) + txn.amount.value
return acc
}, {})
// Compare to budget
const budgetStatus = Object.keys(budget.categories).map((category) => {
const budgeted = budget.categories[category]
const spent = spendingByCategory[category] || 0
const remaining = budgeted - spent
const percentage = (spent / budgeted) * 100
return {
category,
budgeted,
spent,
remaining,
percentage,
status: percentage > 100 ? 'over' : percentage > 80 ? 'warning' : 'ok',
}
})
// Send alerts for overspending
for (const status of budgetStatus) {
if (status.status === 'over') {
await send($.Alert.send, {
to: account.accountHolder,
type: 'budget-exceeded',
message: `You've exceeded your ${status.category} budget by $${Math.abs(status.remaining).toFixed(2)}`,
})
} else if (status.status === 'warning') {
await send($.Alert.send, {
to: account.accountHolder,
type: 'budget-warning',
message: `You've used ${status.percentage.toFixed(0)}% of your ${status.category} budget`,
})
}
}
return budgetStatus
}
// Cash flow forecasting
async function forecastCashFlow(account: BankAccount, days: number = 30) {
// Historical data
const history = await db.list($.FinancialTransaction, {
where: {
$or: [{ sender: account.$id }, { recipient: account.$id }],
transactionDate: {
$gte: subDays(new Date(), 90),
},
},
})
// AI forecasting
const forecast = await ai.predict('cash-flow', {
account,
history,
currentBalance: account.accountBalance.value,
forecastDays: days,
})
return {
currentBalance: account.accountBalance.value,
projectedBalance: forecast.projectedBalance,
expectedIncome: forecast.expectedIncome,
expectedExpenses: forecast.expectedExpenses,
confidence: forecast.confidence,
risks: forecast.risks,
recommendations: forecast.recommendations,
}
}Workflows
Complete Payment Flow
// End-to-end payment workflow
const paymentWorkflow = {
// 1. Initiate payment
initiate: async (params: PaymentParams) => {
const transaction = await processTransaction(params)
return transaction
},
// 2. Validate
validate: on($.Transaction.created, async (txn) => {
await validateTransaction(txn)
}),
// 3. Fraud check
fraudCheck: on($.Transaction.created, async (txn) => {
const fraudResult = await detectFraud(txn)
if (fraudResult.risk === 'high') {
await send($.Fraud.detected, { transaction: txn, fraudCheck: fraudResult })
}
}),
// 4. Process
process: on($.Transaction.process, async (txn) => {
await executeTransaction(txn)
}),
// 5. Settle
settle: on($.Transaction.completed, async (txn) => {
await settleTransaction(txn)
}),
// 6. Reconcile
reconcile: setInterval(async () => {
await runDailyReconciliation(new Date())
}, 86400000), // Daily
}Events
// Account events
on($.Account.opened, async (account) => {
console.log('Account opened:', account.accountNumber)
})
on($.Account.closed, async (account) => {
console.log('Account closed:', account.accountNumber)
})
// Transaction events
on($.Transaction.completed, async (txn) => {
console.log('Transaction completed:', txn.identifier)
})
on($.Transaction.failed, async ({ transaction, error }) => {
console.log('Transaction failed:', transaction.identifier, error)
})
// Fraud events
on($.Fraud.detected, async ({ transaction }) => {
console.log('Fraud detected:', transaction.identifier)
})
// Compliance events
on($.Compliance.alertTriggered, async (alert) => {
console.log('Compliance alert:', alert.type)
})Metrics
// Financial metrics
async function calculateFinancialMetrics() {
// Total deposits
const deposits = await db.aggregate($.BankAccount, {
where: { accountStatus: 'active' },
aggregations: {
total: { $sum: 'accountBalance.value' },
count: { $count: '*' },
},
})
// Transaction volume
const transactions = await db.aggregate($.FinancialTransaction, {
where: {
transactionDate: { $gte: subMonths(new Date(), 1) },
transactionStatus: 'completed',
},
aggregations: {
volume: { $sum: 'amount.value' },
count: { $count: '*' },
},
})
// Fee revenue
const fees = await db.aggregate($.FinancialTransaction, {
where: {
transactionDate: { $gte: subMonths(new Date(), 1) },
transactionStatus: 'completed',
},
aggregations: {
total: { $sum: 'transactionFee.value' },
},
})
return {
totalDeposits: deposits.total,
accountCount: deposits.count,
transactionVolume: transactions.volume,
transactionCount: transactions.count,
feeRevenue: fees.total,
}
}Best Practices
1. Security
- Encryption: Encrypt all sensitive data at rest and in transit
- PCI Compliance: Never store card numbers, CVV, or full PAN
- Access Control: Implement role-based access with audit logs
- Multi-Factor Auth: Require MFA for all high-value operations
- Tokenization: Use tokens for card and bank account data
2. Compliance
- KYC/AML: Verify all customers before account opening
- Transaction Monitoring: Monitor all transactions for suspicious activity
- Record Keeping: Maintain records for regulatory requirements (5-7 years)
- Regulatory Reporting: File SARs, CTRs, and other reports on time
- OFAC Screening: Screen all transactions against sanctions lists
3. Fraud Prevention
- Real-Time Detection: Use AI for real-time fraud detection
- Behavioral Analysis: Track customer behavior patterns
- Device Fingerprinting: Track devices and locations
- Velocity Checks: Monitor transaction frequency and amounts
- Customer Verification: Require additional verification for high-risk transactions
4. Reliability
- Idempotency: Ensure all operations are idempotent
- Atomic Transactions: Use database transactions for consistency
- Retry Logic: Implement exponential backoff for failed operations
- Circuit Breakers: Prevent cascading failures
- Monitoring: Monitor all critical systems 24/7
5. Performance
- Caching: Cache account balances and frequently accessed data
- Async Processing: Use queues for non-critical operations
- Database Optimization: Use proper indexes and query optimization
- Rate Limiting: Protect APIs from abuse
6. Customer Experience
- Real-Time Updates: Provide instant transaction notifications
- Clear Communication: Explain fees, limits, and processes clearly
- Self-Service: Enable customers to manage accounts independently
- Support: Provide 24/7 customer support
- Insights: Give customers visibility into their finances
Complete Implementation
See the full working example at:
Key Takeaways
- Security First: Fintech requires the highest security standards
- Compliance Always: Regulatory compliance is non-negotiable
- Real-Time Processing: Transactions must be fast and reliable
- AI for Fraud: Use AI to detect and prevent fraud
- Customer Trust: Build trust through transparency and reliability
- Audit Everything: Maintain comprehensive audit logs
Next Steps
- Healthcare Platform → - Healthcare management systems
- B2B Platform → - Multi-tenant B2B SaaS
- Architecture Guide → - System design patterns