# 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