Machine Coding Problem

Crypto Exchange

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

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.

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