Machine Coding Problem

Crypto Exchange

macoAllfintechhot/cold-walletblock-confirmation
Commonly Asked By:CoinbaseBinanceRobinhood

Requirements & Scope

Functional Specifications

  • Block Confirmation Monitors: Scans and tracks confirmation heights before crediting deposit values to user accounts.
  • Hot/Cold Wallet Storage: Segregates trade pools into highly-liquid Hot pools (e.g. max 10 BTC) and off-chain vault Cold storages.
  • Large-Value Withdrawal Reviews: Routes transactions exceeding set threshold filters (e.g. > 1 BTC) through dynamic manual audits.
  • Hot Pool Sweepers: Monitors excessive pool capacities and automatically sweeps overflows down to cold vaults.

Exchange Wallet Topology

Exchange entity layouts, blockchain watchers, and audit checkpoints:

Loading...

Design Patterns

  • Observer Pattern (Block Watchers): Distributes block mining events to pending lists, executing checks and version upgrades in parallel.
  • Chain of Responsibility (Approval Filters): Channels withdrawals through rules (limit limits, AML/KYC checks, and multi-sig triggers) sequentially.

Execution Workflows

Deposit & Sweep Logic

  1. Deposit Detection: Receive blockchain notification. Queue entry with Confirmations = 0.
  2. Block Miner Tick: Every mined block increments confirmation counter.
  3. Settle Balance: At 6 confirmations, update matching customer balances, and credit Hot Wallet pool.
  4. Excess Pool Sweep: If Hot Wallet balance > 10.0 BTC, sweep variance to Offline Custody vaults.

Clean Code Blueprint

Production reference implementations demonstrating blockchain monitoring, automatic sweeps, block tracking, and manual reviews:

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

enum TransactionStatus {
    PENDING_CONFIRMATION, CONFIRMED, REJECTED, PENDING_MANUAL_AUDIT, COMPLETED
}

class DepositTransaction {
    private final String id;
    private final String userId;
    private final double amount;
    private final String txHash;
    private int confirmations;
    private TransactionStatus status;

    public DepositTransaction(String userId, double amount, String txHash) {
        this.id = UUID.randomUUID().toString().substring(0, 8);
        this.userId = userId;
        this.amount = amount;
        this.txHash = txHash;
        this.confirmations = 0;
        this.status = TransactionStatus.PENDING_CONFIRMATION;
    }

    public String getId() { return id; }
    public String getUserId() { return userId; }
    public double getAmount() { return amount; }
    public String getTxHash() { return txHash; }
    public int getConfirmations() { return confirmations; }
    public TransactionStatus getStatus() { return status; }

    public void incrementConfirmations(int targetConfirmations) {
        if (this.status != TransactionStatus.PENDING_CONFIRMATION) return;
        this.confirmations++;
        if (this.confirmations >= targetConfirmations) {
            this.status = TransactionStatus.CONFIRMED;
        }
    }
}

class WithdrawalRequest {
    private final String id;
    private final String userId;
    private final double amount;
    private final String targetAddress;
    private TransactionStatus status;

    public WithdrawalRequest(String userId, double amount, String targetAddress) {
        this.id = "WTH_" + UUID.randomUUID().toString().substring(0, 8);
        this.userId = userId;
        this.amount = amount;
        this.targetAddress = targetAddress;
        this.status = amount > 1.0 ? TransactionStatus.PENDING_MANUAL_AUDIT : TransactionStatus.PENDING_CONFIRMATION;
    }

    public String getId() { return id; }
    public String getUserId() { return userId; }
    public double getAmount() { return amount; }
    public String getTargetAddress() { return targetAddress; }
    public TransactionStatus getStatus() { return status; }
    public void setStatus(TransactionStatus status) { this.status = status; }
}

class ExchangeWalletSystem {
    private double hotWalletBalance = 2.0; // Liquidity pool (e.g. BTC)
    private double coldWalletBalance = 98.0; // offline custody
    private static final double HOT_WALLETS_CAP = 10.0; // Max allowed hot liquidity
    
    public double getHotWalletBalance() { return hotWalletBalance; }
    public double getColdWalletBalance() { return coldWalletBalance; }

    public synchronized void creditHotWallet(double amount) {
        this.hotWalletBalance += amount;
        // Sweep check: auto sweep to cold if it exceeds cap
        if (this.hotWalletBalance > HOT_WALLETS_CAP) {
            double excess = this.hotWalletBalance - 2.0; // Keep 2.0 BTC base liquidity
            sweepToCold(excess);
        }
    }

    public synchronized boolean debitHotWallet(double amount) {
        if (this.hotWalletBalance < amount) return false;
        this.hotWalletBalance -= amount;
        return true;
    }

    private void sweepToCold(double amount) {
        this.hotWalletBalance -= amount;
        this.coldWalletBalance += amount;
        System.out.println("SWEEP DAEMON: Swept " + amount + " BTC to Offline Cold custody vault.");
    }

    public synchronized void withdrawFromCold(double amount) {
        if (this.coldWalletBalance < amount) {
            throw new IllegalArgumentException("Cold vault liquidity overflow");
        }
        this.coldWalletBalance -= amount;
        this.hotWalletBalance += amount;
    }
}

class DepositMonitor {
    private final List<DepositTransaction> activeDeposits = new CopyOnWriteArrayList<>();
    private final Map<String, Double> userBalances = new ConcurrentHashMap<>();
    private static final int TARGET_CONFIRMATIONS = 6;
    private final ExchangeWalletSystem walletSystem;

    public DepositMonitor(ExchangeWalletSystem walletSystem) {
        this.walletSystem = walletSystem;
    }

    public void registerDeposit(String userId, double amount, String txHash) {
        activeDeposits.add(new DepositTransaction(userId, amount, txHash));
    }

    public void onNewBlockMined() {
        for (DepositTransaction tx : activeDeposits) {
            if (tx.getStatus() == TransactionStatus.PENDING_CONFIRMATION) {
                tx.incrementConfirmations(TARGET_CONFIRMATIONS);
                if (tx.getStatus() == TransactionStatus.CONFIRMED) {
                    // Credit user balance atomically
                    userBalances.merge(tx.getUserId(), tx.getAmount(), Double::sum);
                    // Credit Hot Wallet liquidity
                    walletSystem.creditHotWallet(tx.getAmount());
                }
            }
        }
    }

    public double getUserBalance(String userId) {
        return userBalances.getOrDefault(userId, 0.0);
    }

    public Map<String, Double> getUserBalances() { return userBalances; }
    public List<DepositTransaction> getActiveDeposits() { return activeDeposits; }
}

class WithdrawalService {
    private final ExchangeWalletSystem walletSystem;
    private final Map<String, Double> userBalances;
    private final List<WithdrawalRequest> requests = new CopyOnWriteArrayList<>();

    public WithdrawalService(ExchangeWalletSystem walletSystem, Map<String, Double> userBalances) {
        this.walletSystem = walletSystem;
        this.userBalances = userBalances;
    }

    public boolean requestWithdrawal(String userId, double amount, String targetAddress) {
        double currentBal = userBalances.getOrDefault(userId, 0.0);
        if (currentBal < amount) return false;

        // Deduct balance instantly to lock fund availability
        userBalances.put(userId, currentBal - amount);

        WithdrawalRequest req = new WithdrawalRequest(userId, amount, targetAddress);
        requests.add(req);

        if (req.getStatus() == TransactionStatus.PENDING_CONFIRMATION) {
            // Process automatically from hot wallet
            if (walletSystem.debitHotWallet(amount)) {
                req.setStatus(TransactionStatus.COMPLETED);
            } else {
                req.setStatus(TransactionStatus.PENDING_MANUAL_AUDIT); // Hot wallet dry-out fallback
            }
        }
        return true;
    }

    public void approveManualWithdrawal(String requestId) {
        for (WithdrawalRequest req : requests) {
            if (req.getId().equals(requestId) && req.getStatus() == TransactionStatus.PENDING_MANUAL_AUDIT) {
                if (walletSystem.debitHotWallet(req.getAmount())) {
                    req.setStatus(TransactionStatus.COMPLETED);
                } else {
                    // Replenish hot wallet from cold storage
                    walletSystem.withdrawFromCold(req.getAmount());
                    walletSystem.debitHotWallet(req.getAmount());
                    req.setStatus(TransactionStatus.COMPLETED);
                }
                break;
            }
        }
    }

    public List<WithdrawalRequest> getRequests() { return requests; }
}

public class Main {
    public static void main(String[] args) {
        ExchangeWalletSystem walletSystem = new ExchangeWalletSystem();
        DepositMonitor depositMonitor = new DepositMonitor(walletSystem);
        WithdrawalService withdrawalService = new WithdrawalService(walletSystem, depositMonitor.getUserBalances());

        System.out.println("=== INITIAL BALANCES ===");
        System.out.println("Hot Wallet: " + walletSystem.getHotWalletBalance() + " BTC");
        System.out.println("Cold Wallet: " + walletSystem.getColdWalletBalance() + " BTC");

        System.out.println("\n=== DEPOSIT PROCESS ===");
        depositMonitor.registerDeposit("alice", 9.0, "0xdeposit_hash");

        for (int block = 1; block <= 6; block++) {
            depositMonitor.onNewBlockMined();
            System.out.println("Block " + block + " mined. Alice Balance: " + depositMonitor.getUserBalance("alice") + " BTC | Hot Wallet: " + walletSystem.getHotWalletBalance() + " BTC");
        }

        System.out.println("Cold Wallet Balance: " + walletSystem.getColdWalletBalance() + " BTC");

        System.out.println("\n=== AUTOMATED WITHDRAWAL ===");
        System.out.println("Alice requests 0.5 BTC withdrawal...");
        withdrawalService.requestWithdrawal("alice", 0.5, "address_xyz");
        System.out.println("Alice balance: " + depositMonitor.getUserBalance("alice") + " BTC | Hot Wallet: " + walletSystem.getHotWalletBalance() + " BTC");

        System.out.println("\n=== LARGE WITHDRAWAL (AUDIT FLOW) ===");
        System.out.println("Alice requests 2.5 BTC withdrawal...");
        withdrawalService.requestWithdrawal("alice", 2.5, "address_abc");
        
        for (WithdrawalRequest req : withdrawalService.getRequests()) {
            System.out.println("Request: " + req.getId() + " | Amount: " + req.getAmount() + " | Status: " + req.getStatus());
            if (req.getStatus() == TransactionStatus.PENDING_MANUAL_AUDIT) {
                System.out.println("Approving " + req.getId() + " manually...");
                withdrawalService.approveManualWithdrawal(req.getId());
                System.out.println("Request Status after audit: " + req.getStatus());
            }
        }

        System.out.println("\n=== FINAL STATE ===");
        System.out.println("Alice Balance: " + depositMonitor.getUserBalance("alice") + " BTC");
        System.out.println("Hot Wallet: " + walletSystem.getHotWalletBalance() + " BTC");
        System.out.println("Cold Wallet: " + walletSystem.getColdWalletBalance() + " BTC");
    }
}

Interactive Simulator

โ– Institutional Custody Crypto Exchange

Block confirmation trackers, hot/cold liquidity ratios, and automated excess-to-cold pool sweeps.

๐Ÿ” Custody Liquidity Split Ratio (Target: 95% Cold / 5% Hot)

๐Ÿ”ฅ Online Hot Wallet Liquidity Pool:3.5000 BTC (3.5%)
๐Ÿ”’ Offline Cold Custody Vault:96.5000 BTC (96.5%)
User Profile: Alice Exchange Account

1.2500 BTC

Verified KYC

๐Ÿ“ฅ Deposit BTC to Exchange

๐Ÿ“ค Withdraw BTC from Exchange

โณ Blockchain Deposit Confirmation Tracker

DEP_901hash: 0x3afb2c...
Amount: 0.85 BTC
3/6 confs

๐Ÿ“‹ Manual Audit Checkpoints

WTH_201
Amount: 2.5 BTC
๐Ÿ–ณ Custody Sweep Daemon Logs
[13:50:00] Deposit scanner online. Awaiting block updates.

๐Ÿ’ฌ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...