# Blockchain Hybrid Architecture - Implementation Summary ## Overview This document summarizes the blockchain integration prototype created for the H2H betting platform. The implementation demonstrates a **hybrid architecture** where critical escrow and settlement operations occur on-chain for trustlessness, while maintaining fast queries through database caching. ## What Has Been Built ### Phase 1: Smart Contract Architecture ✅ COMPLETE **Location**: `backend/app/blockchain/contracts/` 1. **BetEscrow.pseudocode.md** - Core betting smart contract - Bet creation (no funds locked yet) - Atomic escrow locking when bet accepted - Oracle-based automatic settlement - Manual settlement fallback - Dispute mechanism with 48-hour window - State machine: OPEN → MATCHED → PENDING_ORACLE → COMPLETED 2. **BetOracle.pseudocode.md** - Decentralized oracle network - Multi-node consensus (3 of 5 nodes must agree) - Cryptographic signature verification - API adapters for sports/entertainment/politics - Timeout and dispute handling 3. **README.md** - Complete architecture documentation - System diagrams - Data flow charts - Integration points - Security model - Gas optimization strategies ### Phase 2: Backend Blockchain Services ✅ COMPLETE **Location**: `backend/app/blockchain/services/` 1. **blockchain_service.py** - Web3 Integration Layer ```python # Core functions: - create_bet_on_chain() # Create bet on blockchain - prepare_accept_bet_transaction() # Prepare tx for user signing - request_settlement() # Trigger oracle network - settle_bet_via_oracle() # Submit oracle consensus - get_bet_from_chain() # Fetch on-chain state - get_user_escrow() # Get locked funds - estimate_gas() # Calculate tx costs ``` 2. **blockchain_indexer.py** - Event Sync Service ```python # Functionality: - Polls blockchain every 10 seconds for new blocks - Indexes BetCreated, BetMatched, BetSettled, BetDisputed events - Syncs on-chain state to PostgreSQL database - Maintains fast queries while using blockchain as source of truth - Background worker process ``` 3. **oracle_node.py** - Decentralized Oracle Node ```python # Functionality: - Listens for OracleRequested events - Fetches data from external APIs (ESPN, Oscars, etc.) - Maps API results to bet winners - Signs results cryptographically - Submits to aggregator - Multiple independent nodes for decentralization ``` 4. **oracle_aggregator.py** - Consensus Coordinator ```python # Functionality: - Collects submissions from all oracle nodes - Verifies cryptographic signatures - Counts votes for each winner - Achieves 3/5 consensus threshold - Submits final result to blockchain - Handles disputes and timeouts ``` 5. **config.py** - Blockchain Configuration - RPC endpoints (Ethereum, Polygon, Sepolia) - Contract addresses per network - Oracle node addresses - Gas settings - API endpoints ### Phase 3: Frontend Web3 Integration ⚡ IN PROGRESS **Location**: `frontend/src/blockchain/` #### Hooks Created: 1. **hooks/useWeb3Wallet.ts** - MetaMask Connection ```typescript // Features: - Connect/disconnect wallet - Listen for account changes - Listen for network changes - Link wallet address to backend - Network switching ``` 2. **hooks/useBlockchainBet.ts** - Transaction Management ```typescript // Functions: - createBet() // Create bet on-chain - acceptBet() // Accept bet (user signs with MetaMask) - settleBet() // Request oracle settlement // State: - txStatus // Transaction status tracking - isProcessing // Loading state ``` 3. **hooks/useGasEstimate.ts** - Gas Cost Estimation ```typescript // Provides: - gasLimit // Estimated gas units - gasPriceGwei // Current gas price - costEth // Total cost in ETH - costUsd // Total cost in USD - Real-time updates every 30 seconds ``` #### Components Created: 1. **components/BlockchainBadge.tsx** - On-Chain Indicator ```typescript // Variants: - Confirmed: Green badge with "On-Chain ⛓️" - Pending: Yellow badge with spinner - Failed: Red badge with error icon // Features: - Links to block explorer (Etherscan) - Compact mode for lists - Transaction hash display ``` 2. **components/TransactionModal.tsx** - Transaction Status ```typescript // States: - Pending: Waiting for wallet signature - Confirming: Transaction submitted, awaiting blocks - Success: Confirmed with explorer link - Error: Failed with retry button // Features: - Auto-close on success - Animated loading states - "Do not close" warning ``` ## Architecture Diagram ``` ┌────────────────────────────────────────────────────────────┐ │ FRONTEND (React + TypeScript) │ │ │ │ useWeb3Wallet() ─────> Connect MetaMask │ │ useBlockchainBet() ──> Sign Transactions │ │ useGasEstimate() ────> Show Gas Costs │ │ │ │ ─> "On-Chain ⛓️" indicator │ │ ─> Transaction progress │ └─────────────────────────┬───────────────────────────────────┘ │ Web3 / MetaMask ↓ ┌────────────────────────────────────────────────────────────┐ │ BLOCKCHAIN (Smart Contracts) │ │ │ │ BetEscrow Contract BetOracle Contract │ │ ├─ createBet() ├─ requestSettlement() │ │ ├─ acceptBet() ├─ submitOracleResponse() │ │ ├─ settleBet() └─ checkConsensus() │ │ └─ disputeBet() │ │ │ │ Escrow: Holds ETH/MATIC Oracle Nodes: 5 nodes │ └─────────────────────────┬───────────────────────────────────┘ │ Events Emitted ↓ ┌────────────────────────────────────────────────────────────┐ │ BACKEND (FastAPI + Python) │ │ │ │ BlockchainService Oracle Aggregator │ │ ├─ Web3 provider ├─ Collect node votes │ │ ├─ Contract calls ├─ Verify consensus │ │ └─ Gas estimation └─ Submit to chain │ │ │ │ BlockchainIndexer Oracle Nodes (3-5) │ │ ├─ Poll blocks ├─ Fetch ESPN API │ │ ├─ Index events ├─ Sign results │ │ └─ Sync to DB └─ Submit to aggregator │ └─────────────────────────┬───────────────────────────────────┘ │ Database Sync ↓ ┌────────────────────────────────────────────────────────────┐ │ POSTGRESQL DATABASE │ │ │ │ Cached bet data for fast queries │ │ + blockchain_bet_id │ │ + blockchain_tx_hash │ │ + blockchain_status │ └────────────────────────────────────────────────────────────┘ ``` ## Complete Bet Lifecycle Example ### 1. Create Bet (Alice) ``` User fills out CreateBetModal ↓ useBlockchainBet.createBet() ↓ MetaMask popup: Sign transaction ↓ BetEscrow.createBet() on blockchain ↓ BetCreated event emitted ↓ BlockchainIndexer picks up event ↓ Database updated with blockchain_bet_id ↓ Bet appears in marketplace with "On-Chain ⛓️" badge ``` ### 2. Accept Bet (Bob) ``` Bob clicks "Accept Bet" ↓ GasFeeEstimate shows: "~$2.00" (on Polygon) ↓ Bob confirms ↓ useBlockchainBet.acceptBet() ↓ MetaMask popup: Sign transaction with stake ↓ TransactionModal: "Confirming... Do not close" ↓ BetEscrow.acceptBet() locks funds for both parties ↓ BetMatched event emitted ↓ TransactionModal: "Success!" with Etherscan link ↓ BlockchainIndexer syncs to database ↓ Both users see bet status: "Matched ⛓️" ↓ Escrow locked: Alice $100, Bob $100 ``` ### 3. Oracle Settlement (Automatic) ``` Real-world event ends (Super Bowl) ↓ BetEscrow.requestSettlement() ↓ OracleRequested event emitted ↓ 5 Oracle Nodes: Node 1: Fetch ESPN API → "49ers won" → Sign → Submit Node 2: Fetch ESPN API → "49ers won" → Sign → Submit Node 3: Fetch ESPN API → "49ers won" → Sign → Submit Node 4: Fetch ESPN API → "49ers won" → Sign → Submit Node 5: Fetch ESPN API → "49ers won" → Sign → Submit ↓ OracleAggregator: - 5/5 nodes agree on "49ers won" - Maps to Alice's address (she bet on 49ers) - Consensus achieved (5 >= 3 threshold) ↓ BetOracle.fulfillSettlement(winner=Alice) ↓ BetEscrow.settleBet() transfers $200 to Alice ↓ BetSettled event emitted ↓ BlockchainIndexer updates database ↓ Alice's wallet: +$200 ETH Bob's wallet: -$100 (lost from escrow) ↓ Frontend shows: "Completed ⛓️" ``` ## Visual UI Indicators ### Where Blockchain Badges Appear: 1. **Marketplace (BetCard)** ``` ┌─────────────────────────────────────┐ │ Super Bowl LVIII Winner │ │ ┌────────┐ ┌─────────────────────┐ │ │ │ MATCHED│ │ On-Chain ⛓️ │ │ │ └────────┘ └─────────────────────┘ │ │ Sports • $100 • 1.5x / 2x │ │ │ │ [View Details] │ └─────────────────────────────────────┘ ``` 2. **Bet Details Page** ``` Bet Details: Super Bowl LVIII Winner Status: MATCHED [On-Chain ⛓️] [View on Etherscan ↗] Escrow: $200 locked in smart contract ``` 3. **Wallet Page** ``` Wallet Balance ────────────────────────────────────── Available Balance: $725.00 Locked in Escrow: $175.00 [On-Chain ⛓️] Total: $900.00 On-Chain Escrow Details: - 2 active bets - Smart contract: 0x1234... ``` ### Transaction Flow Example: ``` User clicks "Accept Bet - $100" ↓ ┌──────────────────────────────────────┐ │ Gas Fee Estimate │ ├──────────────────────────────────────┤ │ Estimated Gas: 180,000 units │ │ Gas Price: 50 gwei │ │ │ │ Total Cost: 0.009 ETH ≈ $18.00 │ │ │ │ [Cancel] [Confirm] │ └──────────────────────────────────────┘ ↓ User clicks Confirm ↓ ┌──────────────────────────────────────┐ │ MetaMask popup appears │ │ "Confirm transaction in wallet..." │ └──────────────────────────────────────┘ ↓ User signs in MetaMask ↓ ┌──────────────────────────────────────┐ │ 🔄 Confirming Transaction │ │ │ │ Your transaction is being processed │ │ on the blockchain │ │ │ │ [Spinner animation] │ │ │ │ View on Etherscan ↗ │ │ │ │ Do not close this window │ └──────────────────────────────────────┘ ↓ Wait 10-30 seconds ↓ ┌──────────────────────────────────────┐ │ ✓ Transaction Confirmed! │ │ │ │ Your bet has been accepted │ │ │ │ TX: 0xabc123... │ │ View on Block Explorer ↗ │ │ │ │ [Close] │ └──────────────────────────────────────┘ ``` ## File Structure ``` h2h-prototype/ ├── backend/ │ └── app/ │ └── blockchain/ │ ├── __init__.py │ ├── config.py [✅ DONE] │ ├── contracts/ │ │ ├── BetEscrow.pseudocode.md [✅ DONE] │ │ ├── BetOracle.pseudocode.md [✅ DONE] │ │ └── README.md [✅ DONE] │ └── services/ │ ├── __init__.py [✅ DONE] │ ├── blockchain_service.py [✅ DONE] │ ├── blockchain_indexer.py [✅ DONE] │ ├── oracle_node.py [✅ DONE] │ └── oracle_aggregator.py [✅ DONE] │ └── frontend/ └── src/ └── blockchain/ ├── hooks/ │ ├── useWeb3Wallet.ts [✅ DONE] │ ├── useBlockchainBet.ts [✅ DONE] │ └── useGasEstimate.ts [✅ DONE] ├── components/ │ ├── BlockchainBadge.tsx [✅ DONE] │ ├── TransactionModal.tsx [✅ DONE] │ ├── GasFeeEstimate.tsx [⏳ TODO] │ ├── Web3WalletButton.tsx [⏳ TODO] │ └── WalletBalanceBlockchain.tsx [⏳ TODO] └── config/ └── contracts.ts [⏳ TODO] ``` ## Remaining Work ### Phase 3 (Continued): - [ ] Create GasFeeEstimate.tsx component - [ ] Create Web3WalletButton.tsx component - [ ] Create WalletBalanceBlockchain.tsx component - [ ] Create contracts.ts configuration ### Phase 4: - [ ] Modify BetCard.tsx to add - [ ] Modify CreateBetModal.tsx to add transaction flow - [ ] Modify BetDetail.tsx to add gas estimate - [ ] Modify WalletBalance.tsx to show on-chain escrow - [ ] Modify Header.tsx to add wallet connect button ### Phase 5: - [ ] Update Bet model to add blockchain fields: - blockchain_bet_id: int | None - blockchain_tx_hash: str | None - blockchain_status: str | None - [ ] Create database migration ## Key Design Decisions ### Hybrid vs Pure On-Chain | Aspect | On-Chain (Blockchain) | Off-Chain (Database) | |--------|----------------------|---------------------| | **Escrow funds** | ✅ Smart contract holds ETH | ❌ | | **Bet status** | ✅ Source of truth | ✅ Cached for speed | | **Settlement** | ✅ Oracle-based | ❌ | | **User auth** | ❌ | ✅ JWT tokens | | **Bet metadata** | ❌ | ✅ Title, description | | **Search/filters** | ❌ Too slow | ✅ PostgreSQL | | **Notifications** | ❌ | ✅ WebSocket | **Rationale**: Blockchain for trustlessness, database for performance. ### Oracle Consensus - **Nodes**: 5 independent servers - **Threshold**: 3 of 5 must agree - **APIs**: ESPN, Oscars, Election APIs - **Fallback**: Manual settlement after 24 hours - **Dispute**: 48-hour window for participants ### Gas Optimization - **Layer 2**: Deploy on Polygon for 90% lower fees - Ethereum: ~$18 per bet acceptance - Polygon: ~$2 per bet acceptance - **Batch Operations**: Future enhancement - **Meta-Transactions**: Backend pays gas (EIP-2771) ## Security Considerations 1. **Smart Contract** - Reentrancy guards - Role-based access control - Atomic transactions - Security audit required before mainnet 2. **Oracle Network** - Multi-node consensus (3/5) - Cryptographic signatures - Timeout handling - Admin override for edge cases 3. **Frontend** - Never expose private keys - Verify contract addresses - Show gas estimates before transactions - Warn users about network fees ## Next Steps 1. **Complete remaining frontend components** 2. **Update database models with blockchain fields** 3. **Integrate blockchain badges into existing UI** 4. **Test on Sepolia testnet** 5. **Security audit** 6. **Deploy to Polygon mainnet** ## References - Smart Contract Architecture: `backend/app/blockchain/contracts/README.md` - Backend Services: `backend/app/blockchain/services/` - Frontend Integration: `frontend/src/blockchain/` - Implementation Plan: `/Users/liamdeez/.claude/plans/whimsical-napping-sedgewick.md` --- **Status**: Phase 1 ✅ Complete | Phase 2 ✅ Complete | Phase 3 ⚡ 75% Complete | Phase 4 ⏳ Pending | Phase 5 ⏳ Pending