Date: October 17, 2025
Phase: 2A - QR Code Generation & Verification
Implemented complete QR code system for ticket authentication with generation, scanning, and blockchain verification capabilities.
File: frontend/ticketchain/src/hooks/useQRCode.ts
- Dynamic QR Code Generation - Creates QR codes with embedded ticket data
- Data Integrity - Simple hash signature to prevent tampering
- High Error Correction - Level H for better scanning reliability
- Download Functionality - Export QR codes as PNG images
- Expiration Checking - QR codes expire after 24 hours
- Format Validation - Verifies QR code structure and signature
interface QRCodeData {
tokenId: bigint; // NFT token ID
eventId: bigint; // Event ID
owner: string; // Owner's wallet address
contractAddress: string; // TicketNFT contract address
chainId: number; // 42101 (Push Chain Testnet)
timestamp: number; // Generation timestamp
}- Simple hash signature:
generateSimpleHash(data) - Signature verification on scan
- Timestamp validation (24-hour expiry)
- Prevents QR code replay attacks
Note: In production, replace simple hash with proper cryptographic signing (e.g., ECDSA with private key).
File: frontend/ticketchain/src/components/QRCodeDisplay.tsx
{
tokenId: bigint;
eventId: bigint;
owner: string;
showDownload?: boolean; // Default: true
size?: 'sm' | 'md' | 'lg'; // Default: 'md'
className?: string;
}-
Three Size Options:
- Small: 128x128px (w-32)
- Medium: 192x192px (w-48)
- Large: 256x256px (w-64)
-
Loading State - Animated spinner during generation
-
Error Handling - User-friendly error messages
-
Download Button - One-click QR code export
-
Info Display - Shows ticket and event IDs
-
Styling - White background, gray border, shadow effects
<QRCodeDisplay
tokenId={ticketData.tokenId}
eventId={ticketData.eventId}
owner={userAddress}
size="lg"
showDownload={true}
/>File: frontend/ticketchain/src/components/QRScanner.tsx
- Library: html5-qrcode
- Camera: Back-facing (environment mode)
- FPS: 10 frames per second
- Scan Box: 250x250px
- Auto-start/Stop - Manual camera controls
- Real-time Scanning - Continuous QR code detection
- Success Feedback - Green overlay + check icon
- Error Handling - Shows camera/scan errors
- Auto-cleanup - Properly releases camera on unmount
- Responsive Design - Works on mobile and desktop
- Idle (camera off)
- Scanning (camera active)
- Success (QR code detected)
- Error (camera/scan failure)
onScan(decodedText)- Called when QR code is successfully scannedonError(error)- Called on camera or scanning errors
File: frontend/ticketchain/src/pages/OrganizerVerificationPage.tsx
Complete ticket verification system for event organizers to validate tickets at entry.
- QR Code Scan - Decode ticket data
- Format Validation - Verify JSON structure and signature
- Blockchain Verification:
- Read ticket details from TicketNFT contract
- Verify current owner matches QR code owner
- Check if ticket has been used
- Confirm event ID matches
- Display Result - Show verification outcome with color coding
✅ Success (Green Border):
- Owner address matches blockchain
- Ticket is not marked as used
- Event ID matches
- All verifications pass
- Owner mismatch (ticket may have been transferred)
- QR code still valid but requires manual check
❌ Error (Red Border):
- Ticket already used
- Invalid signature
- Expired QR code
- Event ID mismatch
- Invalid format
- Header - Shows organizer address and instructions
- Scanner Section - Camera view with controls
- Verification Result Card:
- Status icon (check/warning/error)
- Status message
- Ticket details (ID, event, owner)
- Verification checklist
- "Scan Next Ticket" button
- Ticket ID with # prefix
- Event ID with # prefix
- Full owner address (truncated in some views)
- Owner verification status
- Used ticket status
File: frontend/ticketchain/src/App.tsx
Added new route:
<Route path="/organizer-scan" element={<OrganizerVerificationPage />} />File: frontend/ticketchain/src/components/Header.tsx
Added "Scan Tickets" link:
- Only visible when wallet is connected
- Located next to "My Tickets" in navigation
- Directs to
/organizer-scan
{
"qrcode": "^1.5.4", // QR code generation
"@types/qrcode": "^1.5.5", // TypeScript types
"qrcode.react": "^4.2.0", // React QR code components
"html5-qrcode": "latest" // QR code scanning
}Removed: react-qr-scanner (React 19 compatibility issues)
-
My Tickets Page - Show QR code for each ticket
{ tickets.map((ticket) => ( <div key={ticket.tokenId}> <TicketCard {...ticket} /> <QRCodeDisplay tokenId={ticket.tokenId} eventId={ticket.eventId} owner={userAddress!} /> </div> )); }
-
Ticket Detail Modal - Full-size QR code with download
<QRCodeDisplay tokenId={selectedTicket.tokenId} eventId={selectedTicket.eventId} owner={userAddress!} size="lg" showDownload={true} />
-
Verification Page - Display after ticket lookup
- Navigation Header - "Scan Tickets" link (when connected)
- Direct URL -
/organizer-scan - Event Detail Page - Could add "Verify Tickets" button for event owners
- ✅ Responsive sizing (sm/md/lg options)
- ✅ Touch-friendly download button
- ✅ Readable on small screens
- ✅ Uses device back camera
- ✅ Full-width scanner box
- ✅ Large touch targets for controls
- ✅ Mobile-optimized scan box (250x250px)
⚠️ Note: Camera permissions must be granted on mobile
- ✅ Responsive layout
- ✅ Full-screen on mobile
- ✅ Large result cards
- ✅ Touch-friendly buttons
- ✅ Readable text sizes
- Generate QR code for ticket
- Download QR code as PNG
- Verify QR code contains correct data
- Check signature validation
- Test expiration (wait 24 hours)
- Test with different ticket IDs
- Grant camera permissions
- Start scanner successfully
- Scan valid ticket QR code
- Verify success animation shows
- Stop scanner successfully
- Test on mobile device
- Test in low light conditions
- Scan valid ticket (should pass)
- Scan used ticket (should fail)
- Scan ticket with wrong owner (should warn)
- Scan expired QR code (should fail)
- Scan invalid/tampered QR code (should fail)
- Scan ticket for different event (should fail)
- Verify blockchain data loads correctly
- Test "Scan Next Ticket" button
- Scanner works on iOS Safari
- Scanner works on Android Chrome
- QR code displays correctly on phone
- Download works on mobile
- Verification page responsive
- Camera switches correctly
- Simple hash-based signature
- 24-hour QR code expiration
- Blockchain verification of ownership and status
-
Cryptographic Signing:
// Replace generateSimpleHash with ECDSA import { ethers } from "ethers"; const signer = new ethers.Wallet(privateKey); const signature = await signer.signMessage(JSON.stringify(data));
-
Backend Verification:
- Move signature generation to backend API
- Verify signatures server-side
- Prevent client-side tampering
-
Rate Limiting:
- Limit QR code generation requests
- Prevent spam scanning attempts
-
Audit Trail:
- Log all scan attempts
- Track ticket usage on-chain
- Create verification history
-
Token Expiration:
- Consider shorter expiration (e.g., event day only)
- Implement dynamic expiration based on event date
-
Camera Permissions:
- User must grant camera access
- No fallback for denied permissions (yet)
-
QR Code Expiration:
- Fixed 24-hour expiration
- Should be tied to event date
-
Offline Scanning:
- Requires network connection for blockchain verification
- No offline mode implemented
-
Simple Signature:
- Not cryptographically secure
- Should be upgraded for production
-
No Ticket Marking:
- Verification doesn't mark ticket as used
- Requires separate transaction (future feature)
-
Mark Ticket as Used:
function markTicketUsed(uint256 tokenId) external onlyOrganizer
-
Offline Verification:
- Cache ticket data
- Sync when online
-
Batch Scanning:
- Scan multiple tickets quickly
- Queue verification requests
-
Analytics Dashboard:
- Show scan statistics
- Entry flow metrics
- Real-time attendance
-
Access Control:
- Only event organizers can verify
- Role-based permissions
-
Multi-Device Sync:
- Multiple scanners per event
- Real-time verification sync
hooks/useQRCode.ts(147 lines) - QR generation and verificationcomponents/QRCodeDisplay.tsx(97 lines) - Enhanced display componentcomponents/QRScanner.tsx(160 lines) - Camera scanner componentpages/OrganizerVerificationPage.tsx(261 lines) - Full verification page
App.tsx- Added/organizer-scanrouteHeader.tsx- Added "Scan Tickets" navigation linkpackage.json- Updated dependencies (removed react-qr-scanner, added html5-qrcode)
docs/qr-code-implementation.md- This file
- Go to "My Tickets"
- View QR code for your ticket
- Download or show on phone
- Present at event entry
- Connect wallet
- Click "Scan Tickets" in header
- Click "Start Scanning"
- Point camera at ticket QR code
- Wait for verification result
- Grant entry if green (success)
- Deny entry if red (error/used)
- Manually verify if yellow (warning)
Status: ✅ Complete - QR code system fully functional and integrated Next Steps: Mobile optimization testing and end-to-end flow testing