From a439389943abcab33de8b60b36b45018bf4dc4f5 Mon Sep 17 00:00:00 2001 From: Gulshan Yadav Date: Sat, 10 Jan 2026 05:53:34 +0530 Subject: [PATCH] feat(web-wallet): add QR code generation and scanning support - Add QRCode component using qrcode.react (SVG-based, H error correction) - Add QRScanner component using html5-qrcode for camera-based scanning - Update Receive page with real QR code and payment request amount - Update Send page with QR scan button to auto-fill recipient address - Support Synor payment URI format: synor:address?amount=X - Add Dockerfile for web wallet with nginx serving - Add web-wallet service to docker-compose.testnet.yml (port 17300) - Fix TypeScript WebCrypto ArrayBuffer type issues QR features: - SVG rendering for crisp display at any size - Error correction level H (30% recovery) for printed codes - Camera permission handling with user-friendly error states - Auto-fill amount when scanning payment requests --- apps/web/Dockerfile | 39 ++++++ apps/web/package.json | 4 +- apps/web/src/components/QRCode.tsx | 100 ++++++++++++++++ apps/web/src/components/QRScanner.tsx | 164 ++++++++++++++++++++++++++ apps/web/src/lib/crypto.ts | 10 +- apps/web/src/lib/transaction.ts | 2 - apps/web/src/lib/wasm-crypto.ts | 6 +- apps/web/src/pages/Receive.tsx | 48 ++++++-- apps/web/src/pages/Send.tsx | 70 +++++++++-- apps/web/src/store/wallet.ts | 1 - docker-compose.testnet.yml | 18 +++ 11 files changed, 430 insertions(+), 32 deletions(-) create mode 100644 apps/web/Dockerfile create mode 100644 apps/web/src/components/QRCode.tsx create mode 100644 apps/web/src/components/QRScanner.tsx diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile new file mode 100644 index 0000000..2b6a98e --- /dev/null +++ b/apps/web/Dockerfile @@ -0,0 +1,39 @@ +# Dockerfile for Synor Web Wallet +# Multi-stage build for optimized production image + +# Stage 1: Build +FROM node:20-alpine AS builder + +WORKDIR /app + +# Install dependencies +COPY package.json ./ +RUN npm install + +# Copy source and build +COPY . . +RUN npm run build + +# Stage 2: Serve with nginx +FROM nginx:alpine AS production + +# Copy build output +COPY --from=builder /app/dist /usr/share/nginx/html + +# Copy custom nginx config for SPA routing +RUN echo 'server { \ + listen 80; \ + root /usr/share/nginx/html; \ + index index.html; \ + location / { \ + try_files $uri $uri/ /index.html; \ + } \ + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { \ + expires 1y; \ + add_header Cache-Control "public, immutable"; \ + } \ +}' > /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/apps/web/package.json b/apps/web/package.json index 6bd271b..50be6bd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -17,7 +17,9 @@ "@noble/hashes": "^1.3.3", "@noble/ed25519": "^2.1.0", "bip39": "^3.1.0", - "zustand": "^4.5.0" + "zustand": "^4.5.0", + "qrcode.react": "^3.1.0", + "html5-qrcode": "^2.3.8" }, "devDependencies": { "@types/react": "^18.3.0", diff --git a/apps/web/src/components/QRCode.tsx b/apps/web/src/components/QRCode.tsx new file mode 100644 index 0000000..2310fd1 --- /dev/null +++ b/apps/web/src/components/QRCode.tsx @@ -0,0 +1,100 @@ +import { QRCodeSVG } from 'qrcode.react'; + +interface QRCodeProps { + value: string; + size?: number; + includeMargin?: boolean; + level?: 'L' | 'M' | 'Q' | 'H'; + className?: string; +} + +/** + * QR Code display component using SVG rendering. + * + * For Synor wallet addresses, the QR code encodes the full address + * in the format: synor: + * + * Error correction levels: + * - L: ~7% recovery + * - M: ~15% recovery (default) + * - Q: ~25% recovery + * - H: ~30% recovery (recommended for addresses) + */ +export function QRCode({ + value, + size = 200, + includeMargin = true, + level = 'H', + className = '', +}: QRCodeProps) { + return ( +
+ +
+ ); +} + +/** + * Generate a Synor payment URI for QR codes. + * Format: synor:
?amount=&label=