The Exchange implements a robust in-memory balance management system that tracks available and locked funds for each user across multiple assets. This ensures users cannot spend the same funds twice and maintains consistency during order execution.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/jogeshwar01/exchange/llms.txt
Use this file to discover all available pages before exploring further.
Balance data structures
User balances are represented using two core types:engine.rs
UserBalances struct containing a HashMap that maps each asset (SOL, USDC, BTC, etc.) to an Amount struct with two fields:
- available: Funds that can be used for new orders or withdrawals
- locked: Funds currently reserved for open orders
The total balance for an asset is
available + locked. Locked funds cannot be used for new orders but are still owned by the user.Engine balance storage
The engine stores all user balances in a thread-safe HashMap:engine.rs
Mutex to enable safe concurrent access. Multiple threads can read or update different users’ balances simultaneously, while the Mutex prevents race conditions when accessing the same user’s balance.
Balance initialization
When a new user is created, their balances are initialized with default amounts:engine.rs
Fund locking mechanism
Before processing an order, the engine validates and locks the required funds:engine.rs
Understanding the fund locking logic
Understanding the fund locking logic
For buy orders (e.g., buying SOL with USDC):
- The user needs quote asset (USDC) to pay for the order
- Lock amount =
price × quantity(total cost in USDC) - Funds move from
availabletolockedfor the quote asset
- The user needs base asset (SOL) to sell
- Lock amount =
quantity(amount of SOL being sold) - Funds move from
availabletolockedfor the base asset
Balance updates during matching
After orders are matched, balances are updated for both parties:engine.rs
Balance state transitions
Here’s what happens during a buy order execution:-
Before matching (in
check_and_lock_funds):- Buyer’s USDC:
available -= total_cost,locked += total_cost
- Buyer’s USDC:
-
After each fill (in
update_user_balance):- Buyer receives SOL:
available += fill.quantity - Buyer’s locked USDC is consumed:
locked -= fill.price × fill.quantity - Seller receives USDC:
available += fill.price × fill.quantity - Seller’s locked SOL is consumed:
locked -= fill.quantity
- Buyer receives SOL:
Notice that locked funds decrease (negative amount) and available funds increase (positive amount) during settlement. The helper function handles both increases and decreases through signed arithmetic.
Helper function for balance updates
All balance modifications go through a single helper function:engine.rs
- Acquires the Mutex lock for the user’s balance
- Finds the specific asset’s balance
- Adds the amount (which can be negative) to either available or locked
- Releases the lock automatically when the function returns
Amount types
TheAmountType enum specifies which balance component to update:
engine.rs
Cancellation and unlocking
When an order is cancelled, locked funds are returned to available:engine.rs
Supported assets
The Exchange supports multiple cryptocurrency assets:types/engine.rs
Precision and decimal handling
All amounts use therust_decimal::Decimal type, which provides:
- Arbitrary precision: No floating-point rounding errors
- Exact arithmetic: Critical for financial calculations
- Fixed-point representation: Maintains decimal places accurately
Using
Decimal instead of f64 is essential for an exchange. Floating-point arithmetic can introduce rounding errors that would be unacceptable in financial applications.Concurrency and thread safety
The balance management system is designed for concurrent access:- Mutex protection: Each user’s balance is protected by its own Mutex
- Fine-grained locking: Only the specific user’s balance is locked during updates
- Parallel processing: Orders for different users can be processed simultaneously
- Deadlock prevention: Locks are acquired and released in consistent order