Meta OA
Summary
I participated in a Meta Online Assessment which featured a complex system design problem to implement a banking system with various functionalities including account management, transactions, and a cashback mechanism.
Full Experience
Banking System // Meta-style Banking System Implementation with Cashback and Prioritized Processing
interface Transaction { timestamp: number; amount: number; }
class Account { id: string; balance: number; history: Transaction[]; cashback: Map<string, { amount: number; processedAt: number, status:"complete"|"in progress" }> = new Map();
constructor(id: string) { this.id = id; this.balance = 0; this.history = []; this.cashback=new Map(); } }
class BankingSystem { private accounts: Map<string, Account> = new Map(); private transactionId = 1;
createAccount(id: string): void { if (this.accounts.has(id)) throw new Error("Account already exists"); this.accounts.set(id, new Account(id)); }
deposit(id: string, amount: number, timestamp: number): void { this.processCashbacks(); const acc = this.getAccount(id); acc.balance += amount; acc.history.push({ timestamp, amount: acc.balance }); }
pay(fromId: string, toId: string, amount: number, timestamp: number): void { this.processCashbacks(fromId, timestamp); this.processCashbacks(toId, timestamp); const from = this.getAccount(fromId); const to = this.getAccount(toId); if (from.balance < amount) throw new Error("Insufficient funds");
const txId = "payment" + this.transactionId++;
from.balance -= amount;
to.balance += amount;
from.history.push({ timestamp, amount:from.balance });
to.history.push({ timestamp, amount: to.balance });
const cashbackAmount = Math.floor((amount * 0.02));
from.cashback.set(txId, { amount: cashbackAmount, processedAt: timestamp + 86400000, status:"IN progress" });
}
transfer(fromId: string, toId: string, amount: number, timestamp: number): void { this.pay(fromId, toId, amount, timestamp); }
getBalanceAt(id: string, timestamp: number, timeAt): number { this.processCashbacks(); const acc = this.getAccount(id); let balance = 0; for (const tx of acc.history) { //return balance of account } return tx.balance; }
paymentStatus(id: string, paymentId: number): 'pending' | 'complete' | 'none' { this.processCashbacks(); //return cashback status }
mergeAccounts(fromId: string, toId: string): void { this.processCashbacks(); const from = this.getAccount(fromId); const to = this.getAccount(toId);
to.balance += from.balance;
to.history.push(...from.history);
//move cashbacks too this.accounts.delete(fromId); }
topSpenders(n: number): string[] { this.processCashbacks(); const spendMap: Map<string, number> = new Map(); for (const [id, acc] of this.accounts) { let total = 0; for (const tx of acc.history) { if (tx.type === 'payment') total += tx.amount; } spendMap.set(id, total); } return Array.from(spendMap.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, n) .map(([id]) => id); }
private getAccount(id: string): Account { const acc = this.accounts.get(id); if (!acc) throw new Error("Account not found"); return acc; }
private processCashbacks(accountId: string, timestamp: number): void {
const acc = this.getAccount(accountId);
for (const [txId, entry] of acc.cashback.entries()) {
if (entry.processedAt <= timestamp) {
acc.balance += entry.amount;
acc.history.push({
timestamp: timestamp,
amount: acc.balance,
});
}
}
} }
Interview Questions (1)
Implement a banking system with the following interfaces and classes:
interface Transaction { timestamp: number; amount: number; }
class Account { id: string; balance: number; history: Transaction[]; cashback: Map<string, { amount: number; processedAt: number, status:"complete"|"in progress" }> = new Map();
constructor(id: string) { this.id = id; this.balance = 0; this.history = []; this.cashback=new Map(); } }
class BankingSystem { private accounts: Map<string, Account> = new Map(); private transactionId = 1;
createAccount(id: string): void { if (this.accounts.has(id)) throw new Error("Account already exists"); this.accounts.set(id, new Account(id)); }
deposit(id: string, amount: number, timestamp: number): void { this.processCashbacks(); const acc = this.getAccount(id); acc.balance += amount; acc.history.push({ timestamp, amount: acc.balance }); }
pay(fromId: string, toId: string, amount: number, timestamp: number): void { this.processCashbacks(fromId, timestamp); this.processCashbacks(toId, timestamp); const from = this.getAccount(fromId); const to = this.getAccount(toId); if (from.balance < amount) throw new Error("Insufficient funds");
const txId = "payment" + this.transactionId++;
from.balance -= amount;
to.balance += amount;
from.history.push({ timestamp, amount:from.balance });
to.history.push({ timestamp, amount: to.balance });
const cashbackAmount = Math.floor((amount * 0.02));
from.cashback.set(txId, { amount: cashbackAmount, processedAt: timestamp + 86400000, status:"IN progress" });
}
transfer(fromId: string, toId: string, amount: number, timestamp: number): void { this.pay(fromId, toId, amount, timestamp); }
getBalanceAt(id: string, timestamp: number, timeAt): number { this.processCashbacks(); const acc = this.getAccount(id); let balance = 0; for (const tx of acc.history) { //return balance of account } return tx.balance; }
paymentStatus(id: string, paymentId: number): 'pending' | 'complete' | 'none' { this.processCashbacks(); //return cashback status }
mergeAccounts(fromId: string, toId: string): void { this.processCashbacks(); const from = this.getAccount(fromId); const to = this.getAccount(toId);
to.balance += from.balance;
to.history.push(...from.history);
//move cashbacks too this.accounts.delete(fromId); }
topSpenders(n: number): string[] { this.processCashbacks(); const spendMap: Map<string, number> = new Map(); for (const [id, acc] of this.accounts) { let total = 0; for (const tx of acc.history) { if (tx.type === 'payment') total += tx.amount; } spendMap.set(id, total); } return Array.from(spendMap.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, n) .map(([id]) => id); }
private getAccount(id: string): Account { const acc = this.accounts.get(id); if (!acc) throw new Error("Account not found"); return acc; }
private processCashbacks(accountId: string, timestamp: number): void {
const acc = this.getAccount(accountId);
for (const [txId, entry] of acc.cashback.entries()) {
if (entry.processedAt <= timestamp) {
acc.balance += entry.amount;
acc.history.push({
timestamp: timestamp,
amount: acc.balance,
});
}
}
} }