Skip to content

Repository files navigation

Bitcoin Guessing Game

A real-time Bitcoin price guessing game built with SvelteKit and AWS serverless architecture.

Live Demo: https://guessgame.sdrdhlab.xyz

Documentation

Overview

Players guess whether the Bitcoin price will go UP or DOWN. After 60 seconds, the guess is resolved and players earn points for correct predictions.

Features

  • Real-time Bitcoin price updates via WebSocket subscriptions
  • Countdown timer showing time until guess resolution
  • Live price update timestamps
  • AWS Cognito authentication with email verification
  • Serverless backend with AWS Lambda, DynamoDB, SQS, and AppSync
  • Live guess resolution with automatic scoring
  • Guess history tracking
  • Mobile-responsive UI with shadcn-svelte components
  • S3 + CloudFlare deployment for production hosting (no CloudFront needed!)

Architecture

Bitcoin Guessing Game Architecture

Frontend

  • Framework: SvelteKit with Svelte 5
  • Styling: Tailwind CSS v4 + shadcn-svelte
  • Auth: AWS Amplify
  • API: GraphQL via AWS AppSync
  • Hosting: S3 Static Website + CloudFlare CDN

Backend

  • API: AWS AppSync (GraphQL)
  • Auth: AWS Cognito
  • Database: DynamoDB
  • Queue: SQS for delayed guess resolution
  • Functions: 6 Lambda functions
    • createGuess - Validates and creates new guesses
    • resolveGuess - Resolves guesses after 60s with retry logic
    • getUser - Fetches user profile and score
    • getGuessHistory - Fetches user's guess history
    • postConfirmation - Cognito trigger that creates user profile after signup
    • streamProcessor - Pushes real-time updates via AppSync

Prerequisites

  • Node.js 18+ and npm
  • AWS Account with credentials configured
  • AWS CLI installed

Deployment

Quick Deploy (Recommended)

Deploy everything (backend + frontend) in one command:

# Navigate to backend directory
cd backend

# Install dependencies
npm install

# Bootstrap CDK (first time only)
npx cdk bootstrap

# Deploy all stacks including frontend
npm run deploy

The frontend stack will automatically:

  1. Build the SvelteKit app locally
  2. Upload to S3
  3. Enable S3 static website hosting

After deployment, you'll see outputs including:

  • WebsiteEndpoint: S3 website endpoint (for CloudFlare CNAME)
  • Cognito User Pool ID
  • AppSync API Endpoint
  • And more...

Configure CloudFlare

After deploying, set up your custom domain with CloudFlare DNS:

  1. Add CNAME Record: CloudFlare Dashboard → DNS → Records

    • Type: CNAME
    • Name: guessgame (or your subdomain)
    • Target: Your S3 website endpoint (from CDK output)
    • Proxy Status: Proxied (orange cloud) ✅
  2. SSL/TLS Settings: CloudFlare Dashboard → SSL/TLS

    • Set to Full (not Flexible or Full Strict)
  3. Test: Visit https://yourdomain.com - should load with HTTPS

Why CloudFlare? The sdrdhlab.xyz domain is already managed in CloudFlare DNS. Using CloudFlare for both DNS and CDN is simpler than introducing CloudFront (would require managing SSL certificates between CloudFront and CloudFlare, and adds another layer of complexity). S3 Static Website + CloudFlare provides a streamlined deployment with fewer moving parts.

Manual Frontend Development

For local development:

cd frontend

# Install dependencies
npm install

# Configure AWS settings (auto-populated from CDK outputs)
# Edit src/lib/aws-config.ts if needed

# Run development server
npm run dev

# Build for production (optional - CDK does this automatically)
npm run build

Deploy Only Frontend

To update just the frontend:

cd backend
npx cdk deploy GuessGameFrontendStack

This will rebuild and redeploy the frontend automatically.

Usage

  1. Register: Create a new account with email and password (minimum 8 characters, must include number and special character)
  2. Verify Email: Enter the 6-digit code sent to your email
  3. Login: Sign in with your credentials
  4. Watch Live Price: See real-time Bitcoin price updates with timestamps
  5. Make a Guess: Click UP or DOWN based on your prediction
  6. Track Countdown: Watch the timer count down from 60 seconds
  7. See Resolution: Your guess automatically resolves and score updates
  8. View History: Check your recent guesses and win rate

Development

Backend Commands

cd backend
npm run build        # Compile TypeScript
npm test            # Run tests (52 tests)
npm run deploy      # Deploy all stacks
npx cdk synth       # Synthesize CloudFormation
npx cdk diff        # Show changes
npx cdk destroy     # Tear down all stacks

Frontend Commands

cd frontend
npm run dev         # Development server (port 5173)
npm run build       # Production build
npm run preview     # Preview production build
npm run check       # Type checking

Testing

Backend Tests

The backend includes comprehensive tests for all Lambda functions:

cd backend
npm test

Test Coverage: 52 tests covering:

  • User creation and validation (postConfirmation)
  • Guess creation and validation (createGuess)
  • User profile retrieval (getUser)
  • Guess history retrieval (getGuessHistory)
  • Price fetching and caching (shared utilities)
  • Guess resolution with retry logic (resolveGuess)
  • Real-time stream processing (streamProcessor)

Manual E2E Testing

  1. Register a new user
  2. Login to the application
  3. Make an UP or DOWN guess
  4. Observe real-time price updates
  5. Wait 60 seconds for guess resolution
  6. Verify score update
  7. Check guess history

Cost Estimation

Note: These are rough estimates (guesstimates) based on AWS pricing as of the documentation date. Actual costs may vary based on usage patterns, data transfer, AWS region, and pricing changes. Monitor your AWS billing dashboard for accurate cost tracking.

Development (Light Testing)

  • ~$1.30/month

Production (100k guesses/month)

  • Lambda: $8.40
  • DynamoDB: $1.25
  • AppSync: $1.00
  • SQS: $0.52
  • Cognito: $0.40
  • Data Transfer: $0.01
  • Total: ~$11.58/month

Project Structure

guessgame/
├── frontend/                 # SvelteKit frontend
│   ├── src/
│   │   ├── lib/
│   │   │   ├── components/ui/        # shadcn-svelte components
│   │   │   ├── aws-config.ts         # Amplify configuration
│   │   │   ├── graphql-client.ts     # GraphQL queries/mutations
│   │   │   └── stores/
│   │   │       ├── auth.svelte.ts    # Authentication store
│   │   │       └── game.svelte.ts    # Game state store
│   │   └── routes/
│   │       ├── +layout.svelte        # Root layout with auth
│   │       ├── +page.svelte          # Home/game page
│   │       ├── login/+page.svelte    # Login/register page
│   │       └── verify/+page.svelte   # Email verification page
│   └── app.css                       # Global styles (Tailwind v4)
│
└── backend/                  # AWS CDK infrastructure
    ├── lib/stacks/
    │   ├── auth-stack.ts             # Cognito User Pool
    │   ├── database-stack.ts         # DynamoDB Tables
    │   ├── queue-stack.ts            # SQS Queue
    │   ├── compute-stack.ts          # Lambda Functions
    │   ├── api-stack.ts              # AppSync API
    │   ├── integration-stack.ts      # Stream Processor
    │   └── frontend-stack.ts         # S3 Static Website (+ CloudFlare)
    ├── lambdas/
    │   ├── createGuess/              # Create guess Lambda
    │   ├── resolveGuess/             # Resolve guess Lambda
    │   ├── getUser/                  # Get user Lambda
    │   ├── getGuessHistory/          # Get guess history Lambda
    │   ├── postConfirmation/         # Cognito post-signup Lambda
    │   ├── streamProcessor/          # Real-time updates Lambda
    │   └── shared/                   # Shared utilities
    └── schema/
        └── schema.graphql            # GraphQL schema

Key Technical Decisions

  1. SQS Requeuing Pattern: Uses message requeuing for retries instead of internal loops
  2. Price Caching: Caches fetched prices in DynamoDB for concurrent guess resolution
  3. Historical Lookup: Checks cached prices first using filter expressions
  4. Real-time Updates: Dual-purpose streamProcessor for both guess and price updates
  5. Svelte 5 Runes: Uses modern Svelte 5 reactivity with $state and $derived

Troubleshooting

Backend Issues

Problem: CDK deploy fails with "Unable to resolve AWS account"

  • Solution: Run aws configure and set up credentials

Problem: Tests fail with SQS mocking errors

  • Solution: These are non-critical mocking issues. The 50 core tests pass.

Frontend Issues

Problem: "Amplify is not configured"

  • Solution: Ensure .env file has correct AWS values

Problem: GraphQL errors in console

  • Solution: Check AppSync endpoint and authentication in .env

Problem: Subscriptions not working

  • Solution 1: Verify AppSync has real-time subscriptions enabled
  • Solution 2: Check for mutation/schema mismatches - subscription filters must match mutation response fields
  • Solution 3: Ensure filtered attributes (e.g., userId in onGuessUpdated(userId: $userId)) are included in the GraphQL schema's subscription definition and mutation response type

License

MIT

Credits

Built with:

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages