A full-stack NFT collectible card game where users solve problems to earn points, purchase digital cards, and mint them as ERC-721 NFTs on the blockchain.
MLSA Cards is a gamified learning platform that combines education with blockchain technology. Users can:
- Solve Problems: Answer questions across multiple categories (Math, Science, Tech, Geography, etc.)
- Earn Points: Get rewarded with points for correct answers
- Collect Cards: Purchase unique skill cards from the store using earned points
- Mint NFTs: Convert owned cards into blockchain-backed NFTs with permanent ownership
- Hybrid Authentication: Login with Google OAuth for easy access or MetaMask for Web3 natives
-
Dual Authentication System
- Google OAuth integration for seamless onboarding
- MetaMask wallet authentication for blockchain users
- Optional wallet linking to enable NFT minting for OAuth users
-
Persistent Data Storage
- SQLite database for user profiles, cards, and progress
- All data persists across sessions and browser clears
-
Problem Solving System
- 50+ questions across 10+ categories
- Real-time point tracking
- Progress saved per user
-
Card Store
- 10 unique collectible cards with different rarities
- Dynamic pricing based on rarity
- Purchase tracking and ownership management
-
NFT Minting
- Server-side transaction signing (gasless for users)
- IPFS metadata storage via Pinata
- ERC-721 compliant smart contract
- Transaction history and on-chain verification
Frontend
- Vanilla JavaScript (no framework)
- Ethers.js v6 for Web3 interactions
- Responsive CSS with modern design
Backend
- FastAPI (Python)
- SQLAlchemy ORM with SQLite
- Authlib for OAuth 2.0
- JWT authentication
- Web3.py for blockchain interactions
Blockchain
- Solidity smart contracts
- Hardhat development environment
- ERC-721 token standard
- Support for Ethereum Sepolia, Polygon Amoy/Mainnet
Storage
- SQLite for application data
- Pinata (IPFS) for NFT metadata
- Node.js 18+ and npm
- Python 3.10+
- MetaMask browser extension
- Google OAuth Credentials (for OAuth login)
- Pinata Account (for IPFS storage)
git clone <your-repo-url>
cd PWcd smart-contracts
npm installCreate .env from .env.example:
cp .env.example .envFill in your .env:
# For local development
ALCHEMY_SEPOLIA_RPC=https://eth-sepolia.g.alchemy.com/v2/your-key
PRIVATE_KEY=your-wallet-private-key
ETHERSCAN_API_KEY=your-etherscan-api-keyDeploy the contract:
For local development:
# Terminal 1: Start Hardhat node
npx hardhat node
# Terminal 2: Deploy
npm run deploy:localFor testnet (Sepolia):
npm run deploy:sepoliaSave the deployed contract address - you'll need it for the backend!
cd ../backend
python -m venv .venv
.\.venv\Scripts\Activate
pip install -r requirements.txtCreate .env from .env.example:
cp .env.example .envConfigure your backend .env:
# Blockchain connection
RPC_URL=http://127.0.0.1:8545
CHAIN_ID=31337
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
CONTRACT_ADDRESS=<your-deployed-contract-address>
# IPFS Storage
PINATA_JWT=your-pinata-jwt-token
# Security
JWT_SECRET=your-strong-random-secret
# CORS
FRONTEND_ORIGIN=http://localhost:8000
# Google OAuth (get from https://console.cloud.google.com/apis/credentials)
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secretSetup Google OAuth:
- Go to Google Cloud Console
- Create a new OAuth 2.0 Client ID
- Add authorized redirect URI:
http://localhost:8000/auth/google/callback - Copy Client ID and Client Secret to
.env
Create card images:
Place card images in backend/static/images/cards/:
- aiml.png
- cloud.png
- web.png
- gd.png
- crpr.png
- broadcast.png
- cyber.png
- arvr.png
- app.png
- video.png
cd backend
.\.venv\Scripts\Activate
uvicorn app.main:app --reload --port 8000Open your browser and navigate to:
http://localhost:8000
Option A: Google OAuth
- Click "Continue with Google"
- Sign in with your Google account
- Automatically creates your profile
Option B: MetaMask
- Click "Connect Wallet"
- Approve MetaMask connection
- Sign authentication message
- Account created with your wallet address
- Navigate to Problems page
- Click "Load a Problem"
- Answer questions correctly
- Earn 2-5 points per correct answer
- Track progress: Solved X / 50 problems
- Go to Store page
- Browse 10 unique cards (10-22 points each)
- Click "Buy Now" on desired cards
- Points deducted automatically
- Cards marked as "Owned" after purchase
- Visit My Cards page
- See all purchased cards with details
- View rarity, description, and purchase date
Requirements:
- Must have wallet linked (MetaMask or linked OAuth account)
- Must own the card you want to mint
Steps:
- Go to My Cards
- Click "๐จ Mint as NFT" on any owned card
- Confirm transaction (server pays gas)
- NFT minted to your wallet address
- View transaction hash and token ID
- Local Hardhat:
31337 - Ethereum Sepolia:
11155111 - Polygon Amoy:
80002 - Polygon Mainnet:
137
Update RPC_URL in backend .env:
- Local:
http://127.0.0.1:8545 - Sepolia:
https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY - Polygon Amoy:
https://polygon-amoy.g.alchemy.com/v2/YOUR_KEY - Polygon Mainnet:
https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY
cd smart-contracts
npm testcd backend
.\.venv\Scripts\Activate
pytest- Gas Payments: Server pays gas for minting (via PRIVATE_KEY in backend .env)
- Security: Never commit
.envfiles to git - Database: SQLite file
mlsa_cards.dbcreated automatically on first run - Metadata: All NFT metadata stored on IPFS via Pinata
- Local Testing: Use Hardhat's default test accounts for development
- Store sensitive keys in
.envfiles (never commit) - Use separate wallets for development and production
- Rotate JWT secrets regularly
- Enable CORS only for trusted origins
- Validate all user inputs on backend
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Open a Pull Request
This project is licensed under the MIT License.
"Auth failed" errors:
- Clear localStorage in browser DevTools
- Ensure JWT_SECRET is set in backend
.env
"Contract not found" errors:
- Verify CONTRACT_ADDRESS in backend
.env - Ensure Hardhat node is running (for local)
- Check RPC_URL and CHAIN_ID match your network
"Insufficient points" errors:
- Solve more problems to earn points
- Check points balance on homepage
Mint fails:
- Ensure wallet is connected
- Verify PRIVATE_KEY has funds for gas
- Check RPC connection
- Confirm contract is deployed
Google OAuth errors:
- Verify redirect URI matches exactly:
http://localhost:8000/auth/google/callback - Check CLIENT_ID and CLIENT_SECRET are correct
- Ensure OAuth consent screen is configured