Files
h2h-prototype/BLOCKCHAIN_IMPLEMENTATION.md
2026-01-02 10:43:20 -06:00

19 KiB

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

    # 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

    # 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

    # 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

    # 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

    // 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

    // 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

    // 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

    // 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

    // 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                     │
│                                                             │
│  <BlockchainBadge /> ─> "On-Chain ⛓️" indicator           │
│  <TransactionModal />─> 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