Meta OA

Posted
28 Jul 2025
337 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.

How it went

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

} }

Questions asked (1)

  1. 01

    Banking System Implementation with Cashback and Prioritized Processing

    System Design · Hard

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

    } }

Know someone preparing? Send it to them:WhatsAppLinkedInX

Interviewed at Meta recently?

Write up your rounds while you still remember the questions. It helps the next person more than you would think.

Share your experience
Discussion 0

Questions for the author, or how your own interview compared.

Join the discussion

Sign in with Google to comment or ask the author a question.

No comments yet

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