SwyftPay
One QR, Any currency, Instant settlement.
The problem SwyftPay solves
💸 The Problem
Crypto and real money don't talk to each other — and that's a billion-dollar gap.
| Pain Point | Reality Today |
|---|---|
| 🔁 Cross-currency transfers | Require CEX accounts, KYC, and 1–3 day settlement |
| 📭 Receiver compatibility | Receiver must also have a crypto wallet |
| 🔐 Wallet addresses | 42-character hex strings — error-prone, unusable for everyday people |
| 💸 On-ramp friction | Converting crypto → INR requires exchange fees + bank delays |
| 🚫 No UPI bridge | India's ₹20 lakh crore/month UPI economy is completely siloed from crypto |
✅ What SwyftPay Solves
SwyftPay lets anyone pay with crypto while the receiver gets INR — instantly, securely, with just a QR scan.
Who uses it?
| User | How SwyftPay helps |
|---|---|
| 👨💻 Crypto holder | Spend AMOY for real-world payments without selling on an exchange |
| 🏪 Merchant / Freelancer | Accept crypto from global clients, receive INR in their UPI account |
| 👨👩👧 Everyday user | Receive payments without needing a wallet — just a SwyftPay account |
| 🌍 Remittance sender | Send value cross-border in seconds vs. SWIFT's 3–5 days |
How it makes things easier
- One QR code replaces wallet addresses — scan and pay in seconds
- No exchange account needed — receiver gets INR directly via Razorpay
- Escrow-backed — funds are locked in a smart contract, no partial execution risk
- < 2 second settlement — on-chain event detected and INR credited instantly
- Non-custodial — SwyftPay never holds your private keys or your funds
How it makes things safer
- 🛡️ Smart contract escrow — rate locked at initiation, no slippage attacks
- 🔏 HMAC-SHA256 signature verification on every Razorpay withdrawal
- 🔑 One wallet per account — enforced at the database level
- 🍪 BetterAuth sessions with HTTP-only cookies — no token leakage
SwyftPay bridges India's ₹20 lakh crore UPI economy with the global crypto ecosystem — making cross-currency payments as simple as showing a QR code.
Challenges we ran into
⚔️ Challenges We Ran Into
1. 📸 The QR Scanner Was Completely Fake
The bug: Our initial "Scan QR" page was a CSS-animated box with a fake scanning line — it had zero actual camera access. Judges would have immediately seen through it.
The fix: We ripped it out entirely and rebuilt it using the browser's native BarcodeDetector API — which actually reads QR codes frame-by-frame from a live getUserMedia camera feed. We added jsQR as a canvas-based fallback for Firefox/Safari where BarcodeDetector isn't supported. The result: a real, working QR scanner with live camera feed.
2. 💸 Razorpay Payouts API Was Locked Behind Business Verification
The bug: Our original plan was for the admin's account to automatically push INR directly to the receiver's UPI ID using Razorpay Payouts API. We built it — then hit a wall. Payouts require a fully KYC-verified Razorpay business account, which can't be activated instantly.
The fix: We pivoted to Razorpay Checkout — the receiver initiates their own withdrawal, the Razorpay payment popup opens with their UPI pre-filled, and our backend verifies the transaction using HMAC-SHA256 signature verification before releasing the balance. This is actually more secure than the original plan — the user authenticates the payout themselves, and our server validates cryptographic proof of payment.
3. ⛓️ Settlement Watcher Missing On-Chain Events
The bug: Our initial settlement watcher polled the blockchain but used a fixed block number — meaning if the server restarted mid-event, the transaction would be silently lost and the receiver would never get credited.
The fix: We rebuilt the watcher to use eth_getLogs with a rolling block range — it tracks the last processed block in memory and resumes exactly where it left off. Every OrderCreated event is caught even across restarts, guaranteeing no missed settlements.
4. 🔧 Next.js Edge Runtime vs Razorpay Node.js SDK
The bug: We tried using the official razorpay npm SDK in our API route — it instantly crashed. Next.js API routes using the Edge runtime don't support Node.js built-ins like crypto.createHmac natively, and the SDK depends on them.
The fix: We switched the API routes to the Node.js runtime (export const runtime = "nodejs") and used the Razorpay REST API directly via fetch for order creation, keeping the SDK only where needed and implementing HMAC verification manually using the built-in crypto module.
5. 🤳 Chrome Detecting Camera but Page Showing Black
The bug: Even though the browser confirmed camera access, the <video> element on the scan page displayed a completely black frame.
The fix: The srcObject assignment on the video element was happening before the element mounted in the DOM, causing a race condition. We moved the getUserMedia call into a useEffect with a ref to the video element, ensuring the stream is only attached after the DOM node exists.
| # | Challenge | How We Solved It |
|---|---|---|
| 1 | Fake QR scanner | Native BarcodeDetector API + jsQR canvas fallback |
| 2 | Razorpay Payouts locked | Pivot to Checkout + HMAC-SHA256 server-side verification |
| 3 | Missed blockchain events | eth_getLogs rolling-block watcher with restart recovery |
| 4 | Edge runtime crash | Switched to Node.js runtime + raw REST API calls |
| 5 | Black camera feed race condition | useEffect + useRef to gate srcObject assignment |
