Machine Coding Problem

Digital Wallet (Advanced)

macoAllfintechserialized-balance-updates
Commonly Asked By:PayPalBlockStripe

Requirements & Scope

Functional Specifications

  • Serialized Dynamic Transfers: Processes transfers with strong transactional consistency across multi-wallet transfers.
  • OCC Conflict Protection: Restricts double-spending by failing/retrying transactions on conflicting version check validations.
  • Auditable Double-Entry Ledger: Every single transaction creates matching Debit and Credit lines synchronously.
  • Real-time Fraud Locks: Dynamically quarantines funds without altering aggregate account registers until review completion.

Architecture & Schema

System components map for balance mutators, fraud services, and reconciling engines:

Loading...

Core Design Patterns

  • Optimistic Concurrency Control (OCC): Avoids heavy lock contention on high-load wallets by comparing versions during writes, ensuring microsecond updates under parallel transactions.
  • Transaction Script Pattern: Orchestrates double-entry ledger entries and CAS statements under single transaction scopes.

Execution Workflows

Transaction CAS Loop Flow

  1. Read Phase: Query current wallet balances, hold levels, and version offsets.
  2. Validate Available Funds: Ensure Balance - Held >= TransferAmount.
  3. Compare-And-Swap Step: Perform atomic check-and-write. If version mismatch occurs, increment retry count and restart loop.
  4. Double-Entry Commit: Append synchronized matching credit and debit entries to the ledger storage.

Clean Code Blueprint

Production reference implementations demonstrating retry loops, CAS, double entry ledger logs, and reconciliation audits:

// โ”€โ”€โ”€ JAVA BLUEPRINT โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
import java.util.*;
import java.util.concurrent.*;

enum WalletStatus {
    ACTIVE, SUSPENDED, UNDER_REVIEW
}

class Wallet {
    private final String walletId;
    private final String ownerName;
    private final String currency;
    private double balance;
    private double heldAmount; // Fraud / auth holds
    private int version; // For OCC
    private WalletStatus status;

    public Wallet(String walletId, String ownerName, double initialBalance, String currency) {
        this.walletId = walletId;
        this.ownerName = ownerName;
        this.balance = initialBalance;
        this.heldAmount = 0.0;
        this.version = 1;
        this.currency = currency;
        this.status = WalletStatus.ACTIVE;
    }

    public String getWalletId() { return walletId; }
    public String getOwnerName() { return ownerName; }
    public synchronized double getBalance() { return balance; }
    public synchronized double getHeldAmount() { return heldAmount; }
    public synchronized double getAvailableBalance() { return balance - heldAmount; }
    public synchronized int getVersion() { return version; }
    public String getCurrency() { return currency; }
    public synchronized WalletStatus getStatus() { return status; }
    public synchronized void setStatus(WalletStatus status) { this.status = status; }

    public synchronized boolean compareAndSwapBalance(double oldBalance, double newBalance, int expectedVersion) {
        if (this.balance == oldBalance && this.version == expectedVersion) {
            this.balance = newBalance;
            this.version++;
            return true;
        }
        return false;
    }

    public synchronized boolean compareAndSwapHold(double oldHold, double newHold, int expectedVersion) {
        if (this.heldAmount == oldHold && this.version == expectedVersion) {
            this.heldAmount = newHold;
            this.version++;
            return true;
        }
        return false;
    }
}

class LedgerEntry {
    private final String entryId;
    private final String debitWalletId;
    private final String creditWalletId;
    private final double amount;
    private final String referenceId;
    private final long timestamp;

    public LedgerEntry(String debitWalletId, String creditWalletId, double amount, String referenceId) {
        this.entryId = UUID.randomUUID().toString();
        this.debitWalletId = debitWalletId;
        this.creditWalletId = creditWalletId;
        this.amount = amount;
        this.referenceId = referenceId;
        this.timestamp = System.currentTimeMillis();
    }

    public String getEntryId() { return entryId; }
    public String getDebitWalletId() { return debitWalletId; }
    public String getCreditWalletId() { return creditWalletId; }
    public double getAmount() { return amount; }
    public String getReferenceId() { return referenceId; }
    public long getTimestamp() { return timestamp; }
}

class WalletService {
    private final Map<String, Wallet> wallets = new ConcurrentHashMap<>();
    private final List<LedgerEntry> ledger = new CopyOnWriteArrayList<>();
    private static final int MAX_OCC_RETRIES = 5;

    public void addWallet(Wallet wallet) {
        wallets.put(wallet.getWalletId(), wallet);
    }

    public Wallet getWallet(String id) {
        return wallets.get(id);
    }

    public boolean transfer(String fromId, String toId, double amount, String referenceId) {
        Wallet from = wallets.get(fromId);
        Wallet to = wallets.get(toId);

        if (from == null || to == null) return false;
        if (from.getStatus() != WalletStatus.ACTIVE || to.getStatus() != WalletStatus.ACTIVE) return false;

        // Resource ordering to prevent deadlock
        Wallet firstLock = fromId.compareTo(toId) < 0 ? from : to;
        Wallet secondLock = fromId.compareTo(toId) < 0 ? to : from;

        int retry = 0;
        while (retry < MAX_OCC_RETRIES) {
            double fromBalance = from.getBalance();
            double fromHold = from.getHeldAmount();
            int fromVersion = from.getVersion();

            double toBalance = to.getBalance();
            int toVersion = to.getVersion();

            if (fromBalance - fromHold < amount) {
                throw new IllegalArgumentException("Insufficient active funds for debit");
            }

            double newFromBalance = fromBalance - amount;
            double newToBalance = toBalance + amount;

            synchronized (firstLock) {
                synchronized (secondLock) {
                    if (from.getVersion() == fromVersion && to.getVersion() == toVersion) {
                        if (from.compareAndSwapBalance(fromBalance, newFromBalance, fromVersion) &&
                            to.compareAndSwapBalance(toBalance, newToBalance, toVersion)) {
                            ledger.add(new LedgerEntry(fromId, toId, amount, referenceId));
                            return true;
                        }
                    }
                }
            }

            retry++;
            try {
                Thread.sleep(10 + ThreadLocalRandom.current().nextInt(15));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
        return false;
    }

    public List<LedgerEntry> getLedger() { return ledger; }
}

class FraudHoldService {
    public boolean placeHold(Wallet wallet, double amount) {
        while (true) {
            double currentHold = wallet.getHeldAmount();
            double available = wallet.getAvailableBalance();
            int currentVersion = wallet.getVersion();

            if (available < amount) return false;

            if (wallet.compareAndSwapHold(currentHold, currentHold + amount, currentVersion)) {
                return true;
            }
        }
    }

    public boolean releaseHold(Wallet wallet, double amount) {
        while (true) {
            double currentHold = wallet.getHeldAmount();
            int currentVersion = wallet.getVersion();

            if (currentHold < amount) return false;

            if (wallet.compareAndSwapHold(currentHold, currentHold - amount, currentVersion)) {
                return true;
            }
        }
    }
}

class BalanceReconciler {
    public boolean reconcile(Wallet wallet, List<LedgerEntry> ledger, double initialBalance) {
        double credits = ledger.stream()
            .filter(e -> e.getCreditWalletId().equals(wallet.getWalletId()))
            .mapToDouble(LedgerEntry::getAmount).sum();

        double debits = ledger.stream()
            .filter(e -> e.getDebitWalletId().equals(wallet.getWalletId()))
            .mapToDouble(LedgerEntry::getAmount).sum();

        double expectedBalance = initialBalance + credits - debits;
        return Math.abs(wallet.getBalance() - expectedBalance) < 0.001;
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("=== DIGITAL WALLET ADVANCED DEMO (JAVA) ===");

        WalletService walletService = new WalletService();
        FraudHoldService fraudHoldService = new FraudHoldService();
        BalanceReconciler reconciler = new BalanceReconciler();

        Wallet alice = new Wallet("W_ALICE", "Alice", 500.0, "USD");
        Wallet bob = new Wallet("W_BOB", "Bob", 250.0, "USD");
        Wallet system = new Wallet("W_SYSTEM", "System Escrow", 1000.0, "USD");

        walletService.addWallet(alice);
        walletService.addWallet(bob);
        walletService.addWallet(system);

        System.out.println("Initial balances:");
        System.out.println("Alice: $" + alice.getBalance() + " (v" + alice.getVersion() + ")");
        System.out.println("Bob: $" + bob.getBalance() + " (v" + bob.getVersion() + ")");

        System.out.println("\n--- Executing OCC Transfer: System to Alice $150 ---");
        boolean t1 = walletService.transfer("W_SYSTEM", "W_ALICE", 150.0, "TX_101");
        System.out.println("Transfer Success: " + t1);
        System.out.println("Alice Balance: $" + alice.getBalance() + " (v" + alice.getVersion() + ")");

        System.out.println("\n--- Placing Fraud Hold of $50 on Bob ---");
        boolean h1 = fraudHoldService.placeHold(bob, 50.0);
        System.out.println("Hold Placed: " + h1);
        System.out.println("Bob Total Balance: $" + bob.getBalance());
        System.out.println("Bob Available Funds: $" + bob.getAvailableBalance());

        System.out.println("\n--- Performing Audit Reconciliation ---");
        boolean aliceReconciled = reconciler.reconcile(alice, walletService.getLedger(), 500.0);
        System.out.println("Alice Ledger Reconciled: " + aliceReconciled);
    }
}

Interactive Simulator

โ– Fintech Core Digital Wallet Simulator

Optimistic Concurrency Control (OCC) triggers, double-entry ledger audits, and real-time fraud locks.

Alice Dev

ID: W1
ver: 1
Total Balance:$500.00
Fraud holds:-$0.00
Available Funds:$500.00

Bob Trader

ID: W2
ver: 1
Total Balance:$250.00
Fraud holds:-$50.00
Available Funds:$200.00

System Escrow

ID: W3
ver: 1
Total Balance:$1000.00
Fraud holds:-$0.00
Available Funds:$1000.00

๐Ÿ’ธ Execute Balance Transfer (OCC CAS)

๐Ÿ”’ Fraud Quarantine Holds

๐Ÿ—’๏ธ Double-Entry Ledger Book

TX_1001Escrow Grant
Debited: W3 | Credited: W1
$150.00
TX_1002Escrow Grant
Debited: W3 | Credited: W2
$50.00
๐Ÿ–ณ Wallet Engine Daemon Logs
[13:50:00] Digital wallet ledger initialized. Balances synced.

๐Ÿ’ฌReview

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...