Functional Scope (In-Scope)
- Atomic Money Transfers: Perform money transactions securely ensuring complete atomic credit and debit steps.
- Zero Floating-Point Errors: Use arbitrary-precision decimals (BigDecimal) to avoid float calculation flaws.
- Strict Idempotency: Check idempotency keys before transaction processing to block duplicates.
- Command Pattern for Rollbacks: Encapsulate operations inside Command objects, supporting robust undo/rollback mechanisms.
- Append-Only Event Ledger: Maintain immutable transactional histories.
Explicit Boundaries (Out-of-Scope)
- No Real Bank Card Integration: Bypasses live Visa/Mastercard processing flows or clearinghouses.
- No Multi-Currency FX Engine: Overwrite parameters do not calculate real-time FX exchange conversion spreads.
Thread-safe, command-pattern-driven financial transfer blueprints in Java and Python:
// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
enum TransactionStatus { PENDING, SUCCESS, FAILED, ROLLED_BACK }
interface TransactionCommand {
boolean execute();
void undo();
String getId();
TransactionStatus getStatus();
BigDecimal getAmount();
}
class Wallet {
private final String id;
private BigDecimal balance;
private final ReentrantLock lock = new ReentrantLock();
public Wallet(String id, BigDecimal initialBalance) {
this.id = id;
this.balance = initialBalance;
}
public String getId() { return id; }
public BigDecimal getBalance() {
lock.lock();
try {
return balance;
} finally {
lock.unlock();
}
}
public ReentrantLock getLock() { return lock; }
public boolean debit(BigDecimal amount) {
if (balance.compareTo(amount) >= 0) {
balance = balance.subtract(amount);
return true;
}
return false;
}
public void credit(BigDecimal amount) {
balance = balance.add(amount);
}
}
class P2PTransferCommand implements TransactionCommand {
private final String id;
private final Wallet source;
private final Wallet destination;
private final BigDecimal amount;
private TransactionStatus status;
public P2PTransferCommand(String id, Wallet source, Wallet destination, BigDecimal amount) {
this.id = id;
this.source = source;
this.destination = destination;
this.amount = amount;
this.status = TransactionStatus.PENDING;
}
@Override
public boolean execute() {
// Sort locks alphabetically by wallet ID to ensure deadlock immunity
Wallet first = source.getId().compareTo(destination.getId()) < 0 ? source : destination;
Wallet second = source.getId().compareTo(destination.getId()) < 0 ? destination : source;
first.getLock().lock();
try {
second.getLock().lock();
try {
if (source.debit(amount)) {
destination.credit(amount);
status = TransactionStatus.SUCCESS;
return true;
} else {
status = TransactionStatus.FAILED;
return false;
}
} finally {
second.getLock().unlock();
}
} finally {
first.getLock().unlock();
}
}
@Override
public void undo() {
if (status != TransactionStatus.SUCCESS) return;
Wallet first = source.getId().compareTo(destination.getId()) < 0 ? source : destination;
Wallet second = source.getId().compareTo(destination.getId()) < 0 ? destination : source;
first.getLock().lock();
try {
second.getLock().lock();
try {
if (destination.debit(amount)) {
source.credit(amount);
status = TransactionStatus.ROLLED_BACK;
}
} finally {
second.getLock().unlock();
}
} finally {
first.getLock().unlock();
}
}
public String getId() { return id; }
public TransactionStatus getStatus() { return status; }
public BigDecimal getAmount() { return amount; }
}
class WalletService {
private final Map<String, Wallet> wallets = new ConcurrentHashMap<>();
private final Map<String, TransactionCommand> idempotencyStore = new ConcurrentHashMap<>();
private final List<TransactionCommand> ledger = new CopyOnWriteArrayList<>();
public void registerWallet(Wallet wallet) {
wallets.put(wallet.getId(), wallet);
}
public Wallet getWallet(String id) {
return wallets.get(id);
}
public TransactionCommand executeTransfer(String idempotencyKey, String srcId, String destId, BigDecimal amount) {
if (idempotencyStore.containsKey(idempotencyKey)) {
System.out.println("[Service] Returning cached transaction for idempotency key: " + idempotencyKey);
return idempotencyStore.get(idempotencyKey);
}
Wallet src = wallets.get(srcId);
Wallet dest = wallets.get(destId);
if (src == null || dest == null) {
throw new IllegalArgumentException("Invalid wallets involved in transfer");
}
String txnId = "TXN-" + UUID.randomUUID().toString().substring(0, 8);
TransactionCommand command = new P2PTransferCommand(txnId, src, dest, amount);
command.execute();
ledger.add(command);
idempotencyStore.put(idempotencyKey, command);
return command;
}
public void rollbackTransaction(String txnId) {
for (TransactionCommand cmd : ledger) {
if (cmd.getId().equals(txnId)) {
cmd.undo();
System.out.println("[Service] Successfully rolled back Transaction: " + txnId);
return;
}
}
System.out.println("[Service] Transaction not found for rollback: " + txnId);
}
public List<TransactionCommand> getLedger() {
return Collections.unmodifiableList(ledger);
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== Digital Wallet Concurrent Simulation ===");
WalletService service = new WalletService();
Wallet w1 = new Wallet("ACC-01", new BigDecimal("1000.00"));
Wallet w2 = new Wallet("ACC-02", new BigDecimal("500.00"));
service.registerWallet(w1);
service.registerWallet(w2);
ExecutorService executor = Executors.newFixedThreadPool(2);
// Concurrent overlapping payments between ACC-01 and ACC-02 (locks are ordered, preventing deadlocks)
executor.submit(() -> {
service.executeTransfer("KEY-101", "ACC-01", "ACC-02", new BigDecimal("200.00"));
});
executor.submit(() -> {
service.executeTransfer("KEY-102", "ACC-02", "ACC-01", new BigDecimal("100.00"));
});
executor.shutdown();
executor.awaitTermination(2, TimeUnit.SECONDS);
System.out.println("ACC-01 Balance: " + w1.getBalance());
System.out.println("ACC-02 Balance: " + w2.getBalance());
// Perform a rollback simulation
TransactionCommand lastTxn = service.getLedger().get(0);
System.out.println("\nRolling back transaction: " + lastTxn.getId() + " of amount: " + lastTxn.getAmount());
service.rollbackTransaction(lastTxn.getId());
System.out.println("ACC-01 Balance after rollback: " + w1.getBalance());
System.out.println("ACC-02 Balance after rollback: " + w2.getBalance());
}
}