Inspiration
Prediction markets like Polymarket surface collective intelligence more accurately than polls or pundits, but no equivalent exists for Singapore-specific events. We built HEAP to bring a production-grade, blockchain-settled prediction market to the Singapore context.
What it does
HEAP is a limit-order prediction market platform where users connect a MetaMask wallet, deposit USDC on Polygon Amoy testnet, and trade YES/NO shares on event outcomes. Five independent TypeScript microservices handle authentication (sessions via Redis, MetaMask ECDSA wallet linking), order management (collateral reservation, idempotent order creation), CLOB trade matching (price-time priority against a Redis order book), market data (live prices, order book depth, positions), and trade settlement (balance updates, on-chain payouts, UMA oracle resolution). A scheduler service runs four EventBridge-backed jobs: market expiry every minute, oracle result checks every five minutes, blockchain transaction confirmation every minute, and ledger reconciliation every fifteen minutes.
How we built it
- Runtime: Node.js + TypeScript across all services, each independently runnable
- Storage: MongoDB for durable state (orders, trades, balances, positions, outbox events), Redis for hot order book (sorted sets for bid/ask price levels), session store, and distributed locks
- Async pipeline: SQS FIFO queue (matching-order-queue.fifo) for serialised order mutations per market-outcome pair; trade-settlement-queue for downstream settlement; blockchain-transaction-queue for on-chain writes, all simulated locally via LocalStack
- Reliability: Transactional outbox pattern: services write events to MongoDB outbox-events collection inside atomic multi-document transactions; a publisher loop reads and forwards to SQS with retry
- Blockchain: Polygon Amoy testnet (chain ID 80002), smart contracts in /contracts, Alchemy as RPC provider, UMA oracle for market resolution
- Infrastructure: Docker dev containers for reproducible local environments, LocalStack for AWS service simulation
Challenges we ran into
- Atomic multi-collection writes: Coordinating balance deduction, order creation, ledger entry, and outbox event publish inside a single MongoDB transaction without partial state was the hardest constraint to get right
- FIFO ordering: The matching engine must process orders for the same market-outcome strictly in sequence, solved with SQS FIFO messageGroupId keyed to marketid:outcome Idempotency everywhere: Every mutating operation carries an idempotency key stored in Redis (TTL 24h–7d) to handle SQS redeliveries safely without double-spending or duplicate trades
- LocalStack parity: Replicating EventBridge scheduler behaviour and SQS FIFO semantics locally with LocalStack required careful queue provisioning in the scheduler bootstrap
What we learned
- How distributed systems handle consistency without two-phase commit: the outbox pattern is the practical answer
- Order book mechanics: bid/ask sorted sets, price-time priority, partial fill accounting, maker/taker distinction
- Why FIFO queues with message group IDs matter when multiple services mutate shared state concurrently
- Blockchain integration complexity: RPC providers, transaction lifecycle (pending → broadcasted → confirmed → failed), and oracle dispute windows
What's next for HEAP Polymarket
- Deploy to AWS ECS (ap-southeast-1) with Application Load Balancer routing, behind CloudFront and WAF as designed
- Migrate from Polygon Amoy testnet to Polygon mainnet with real USDC
- Add frontend UI to the existing /ui service beyond the current dev scaffold
- Expand market categories beyond the seeded set to cover Singapore-specific events (elections, NDR, sports)
- Implement the Lambda reconciliation jobs for order book, balance, and blockchain drift detection
Built With
- mongodb
- node.js
- polygon
- sqs
- typescript
Log in or sign up for Devpost to join the conversation.