Midl
A decentralized P2P exchange enabling crypto on/off-ramping for any fiat currency via collateralized custodians.
Architecture Overview
A hybrid Event-Sourced architecture sized for 10,000+ concurrent users. The blockchain handles custody and dispute resolution, while a NestJS backend implements a custom UTXO indexer to track asset provenance and fee splits.
The Challenges
Problem
The underlying blockchain (Alacrity/EOSIO) does not support native event emission (like Solidity's `emit`). We needed a way for the backend to react instantly to on-chain actions (Trades, Disputes) without brutally polling the entire block state.
Solution
Engineered a 'Side-Effect Contract' pattern. Whenever a main contract executed a critical action, it made an inline call to a separate, hollow 'Logger Contract' with structured data. Our indexer listened specifically for interactions with this Logger address, effectively synthesizing an event log on a chain that didn't support one.
IndexerUtils.ts / LoggerContract.cpp
Problem
The business logic required a 'Sticky Fee' model: A $0.20 transfer fee had to be split between the platform and the *specific* custodian who originally facilitated the minting of those tokens, even after the tokens had changed hands 50 times.
Solution
Rejected a simple 'Account Balance' model in favor of a full UTXO (Unspent Transaction Output) architecture within MongoDB. Every token unit is tracked as a unique `Batch` document with a `previousBatchId`. When a transfer happens, we traverse the graph backward to identify the original `facilitator` and route the fee correctly.
batch.schema.ts / batch.service.ts
Problem
Custodians could only accept orders up to 80% of their staked liquid capital. We needed a real-time matching engine that wouldn't allow race conditions (e.g., two users claiming the same custodian liquidity simultaneously).
Solution
Implemented a dual-layer lock. On-chain, the `createreqdep` action atomically moves funds from `free_amount` to `tied_amount`. Off-chain, the NestJS matcher uses MongoDB transactional sessions to reserve liquidity before broadcasting the 'Match Found' event via authenticated WebSockets. Every write on the payment path is idempotent and guarded by a distributed lock, which is what holds the ledger consistent at 10,000+ concurrent users.
transaction.service.ts
Problem
Since this is P2P, users can lie about sending fiat. We needed a decentralized way to resolve 'He said, She said' conflicts without a centralized admin key.
Solution
Built a 4-phase on-chain judicial system (`Regular` → `Dispute` → `Appeal` → `Resolved`). Randomly selected 'Jury' users stake tokens to vote on evidence. The smart contract holds the disputed funds and programmatically slashes the loser's stake to pay the winner and the jury, ensuring economic alignment.
midl.cpp (resolve / opendispute)