Inspiration
In India, getting a loan means surrendering your financial life. Bank statements, salary slips, PAN, Aadhaar, employment letters all handed over to lenders, aggregators, and "verification" services, then stored indefinitely on servers we'll never see. Every credit pull leaves a permanent footprint. Every rejected application teaches some database a little more about you. We kept asking the same question: why does proving you're creditworthy require giving up everything that makes you, you? A lender doesn't need to see your salary, they need to know it clears a threshold. They don't need your full repayment history, they need to know you don't default. That gap, between what's shared and what's actually needed, is exactly what zero-knowledge proofs were invented for. When we found Midnight Network — a privacy-native blockchain built around ZK by default; we knew this was the stack we'd been waiting for. The name Nocturned felt right: credit, in the dark, the way it should be.
What it does
Nocturned is a full two-sided credit and lending dApp.
On the borrower side, users get a CIBIL-aligned score (300–900) computed from 15 financial signals across payment history, credit utilization, FOIR (fixed obligation to income ratio), employment stability, and tax compliance (ITR filing). Data comes in three ways: CSV bank-statement upload, PAN-based bureau lookup (40 realistic demo profiles), or a manual form. The engine produces a tier: Prime (780+) → up to ₹25L at 10.5% APR Gold (690–779) → up to ₹12L at 14% APR Silver (600–689) → up to ₹5L at 18% APR Bronze (510–599) → up to ₹1.5L at 24% APR Each score result also surfaces the top 3 improvement actions — the highest-leverage changes a user can make to climb a tier (drop utilization below 30%, file ITR, etc.).
On the lender side, banks get a dedicated dashboard with a live WebSocket feed of incoming applications, a multi-lender marketplace where they can post offers, and a counter-offer flow so borrowers and lenders can negotiate without the bank ever seeing the underlying financial data — only the proven tier. On chain, the credit_lending.compact contract verifies tier-membership proofs on Midnight (v4 preprod, real deploy path through a dedicated /deploy page). Once a loan is issued, the backend generates a full amortisation schedule (annuity-formula EMIs with principal/interest breakdown), tracks paid EMIs, and links each repayment to its Midnight tx hash. The loop closes when the final EMI is paid and loan_repaid flips true
How we built it
Frontend: React 18 + Vite + TypeScript + Tailwind. Animated CIBIL gauge, multi-mode score entry, wallet connect via Lace, role-based routing (borrower vs bank), and a dashboard that ties scores → reports → marketplace offers → active loans → repayment schedules. Backend: FastAPI + Redis. JWT cookie auth (httponly + secure), CSRF via custom X-Nocturne-Request header, per-email rate limiting with proper Retry-After headers to v2 spec, account lockout after 5 failed logins, and at-rest encryption of all report payloads (sealed before they hit Redis, opened only on read with the user's id as part of the key). The scoring engine is pure Python — deterministic, auditable, unit-tested. The amortisation engine is also a pure module (backend/credit/amortisation.py) so the same schedule renders identically across runs and tests. Blockchain: credit_lending.compact written in Midnight's Compact language. The circuit takes the score commitment + tier threshold and emits a proof that the score clears the threshold without revealing it. Wallet integration via Lace; proofs generated by the Midnight proof server. We wired the real Midnight v4 deploy/apply path (not just a stub) and built a /deploy page so the contract address is established before any loan goes through. Real-time layer: WebSocket feed pushes new loan applications and counter-offers to bank dashboards live, no polling. Data layer: Redis only — no durable cleartext storage. Sealed reports, sessions, rate-limit counters, all behind a small surface area that keeps the privacy story honest.
Challenges we ran into
- PAN bureau access is gated by regulation, not technology. Real CIBIL / Experian / Equifax APIs require an RBI-licensed NBFC partnership and weeks of paperwork. We solved it for the demo with a realistic mock layer — 40 personas with deterministic responses and 1.6s latency — and documented the exact integration points for production (Account Aggregator framework + bureau licensing).
- Midnight tooling is early. The proof server runs locally, the indexer is preprod-only, and the Compact compiler has rough edges. The jump from "stubbed apply" to "real v4 deploy + apply" cost more debugging hours than any other part of the project — witness types, serialization mismatches, contract-address bootstrapping. Worth it. The privacy guarantees are real.
- Designing for "no data leaves the device" without sacrificing UX. The CSV parser, feature extractor, and score commitment all run in the browser. Making it reliable across formats while keeping the bundle reasonable — and then sealing whatever does land on the backend — took serious effort. Rate limiting that doesn't feel hostile. A naive 429 frustrates real users. Tightening to the v2 spec meant adding accurate Retry-After headers, separating score / auth / counter-offer limits, and making the frontend back off cleanly instead of showing red errors.
- Closing the loop on repayment. Issuing a loan is half the story — without a schedule, EMI tracking, and a repayment endpoint, the dApp is just a fancy approval page. Building the amortisation engine (annuity formula, month-clamping for Feb 29, paid/due/overdue/upcoming status, idempotent generation) was the last piece that turned Nocturned into a real lending product instead of a credit-check demo.
- Balancing demo polish with substance. It would have been easy to fake everything behind a pretty dashboard. We kept the scoring engine, the auth stack, the encryption, the marketplace, the amortisation schedule, and the contract real — even when it cost us sleep.
Accomplishments that we're proud of
What we learned
- ZK isn't just cryptography, it's API design. The hardest part wasn't writing the Compact circuit — it was deciding what to prove. Every additional field in the witness leaks information through correlation. We rewrote the contract twice before landing on tier-membership as the only public output.
- CIBIL is a black box, but FOIR isn't. Indian lenders care about EMI-to-income ratio more than any single number. Rebuilding scoring around FOIR as a first-class signal — not a side calculation — made the tiers actually map to real lending decisions.
- Two-sided marketplaces force honesty. The moment we added the bank dashboard, every shortcut on the borrower side became obvious. Building both sides in parallel kept us from faking the parts a single-sided demo would let us hide.
- Privacy UX is a real discipline. Users don't trust "private by default" unless the UI proves it. Explicit "this never leaves your browser" indicators on the CSV path, visible at-rest encryption status, and a deploy page that shows the user the actual contract address — all small things, big trust impact.
- Two people, clear lanes, P1 ordering. We split frontend/backend cleanly and committed to a P1-ordered backlog over parallel feature sprawl. Shipping v2 (encryption, rate limits, anonymized datasets, real Midnight wiring) before touching the marketplace meant the demo never broke.
What's next for Nocturned
- Integrate India's Account Aggregator (AA) framework (Finvu / OneMoney / CAMS) for consented, real-time bank data — the cleanest legal path to live financial signals.
- Add partial-payment and prepayment support to the amortisation engine.
- Open-source the scoring and amortisation engines so the methodology is independently auditable. Nocturne is our bet that the future of credit isn't more data collection — it's less.
Built With
- aes
- axios
- compact-language
- docker
- fastapi
- jwt
- midnight
- midnight-network-(preprod-v4)
- pydantic
- python-3.11
- react-18
- react-router
- redis
- tailwind-css
- typescript
- uvicorn
- vite
- websockets
Log in or sign up for Devpost to join the conversation.