Meta OA

meta logo
meta
July 28, 20253 reads

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)

Q1
Banking System Implementation with Cashback and Prioritized Processing
System DesignHard

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,
    });
  }
}

} }

Discussion (0)

Share your thoughts and ask questions

Join the Discussion

Sign in with Google to share your thoughts and ask questions

No comments yet

Be the first to share your thoughts and start the discussion!