Skip to content

gomugomucode/Yatra

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

90 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Status: Live Beta

· YATRA

The DePIN Transport Protocol for South Asia

Real-time tracking · Soulbound receipts · ZK identity · On-chain reputation

Every journey, verified. Every driver, accountable. Every rupee, traceable.


Launch App · Documentation · Contributing


Next.js Solana Firebase TypeScript Three.js ZK License


Why Yatra Exists

Nepal operates 12,000+ public buses carrying millions of passengers daily. Not a single trip produces a verifiable digital record. Drivers build years of service history that vanishes when they switch operators. Passengers receive paper tickets that disintegrate in their pockets. Transport regulators have zero real-time visibility into fleet operations. And across the broader South and Southeast Asian gig economy — 50 million ride-sharing drivers — reputation is locked inside platforms that can erase it overnight.

Yatra fixes this by combining three technologies that have never been unified in a single transit product:

Problem Yatra's Answer
Passengers cannot track buses Real-time GPS with sub-3-second latency via Firebase Realtime DB
No verifiable driver identity Zero-knowledge proof (Groth16) anchored on Solana — identity verified without exposing documents
No immutable trip records Soulbound NFT receipt (Token-2022 NonTransferable) minted to the passenger's wallet on every trip
Driver reputation is not portable On-chain DriverReputation PDA readable by any dApp without permission
No trustless fare payment GPS-verified escrow — fare releases only when geofence confirms drop-off

Product

For Passengers (यात्री)

  • Live bus tracking — see every nearby driver within 10km on an interactive map, updated every 3 seconds
  • One-tap hailing — select a driver, set your pickup point, and send a request that only that driver receives
  • Two-phase ETA — Phase 1: driver's ETA to your pickup pin. Phase 2: ETA to your destination after boarding
  • Route visualization — real-time polyline drawn from driver to pickup (cyan) and driver to destination (blue) via OSRM
  • Soulbound trip receipt — a non-transferable NFT minted to your Solana wallet after every completed trip
  • Proximity alerts — geofenced notifications at 500m, 200m, and 50m as the bus approaches
  • Loyalty tiers — Bronze (5 trips), Silver (10), Gold (25) — on-chain badges that unlock priority booking

For Drivers (चालक)

  • ZK identity onboarding — verify your license and age via a Groth16 zero-knowledge proof. No raw documents leave your device
  • Command center — cockpit-style dashboard to manage route, seats, and live passengers
  • Trip request panel — incoming requests slide up with a 90-second countdown. Accept or reject with one tap
  • On-chain trip logs — every completed trip updates your DriverReputation PDA on Solana
  • Portable reputation — your score (0–1000) is readable by any other transit app, insurance protocol, or DeFi lending platform
  • SOS emergency system — one-tap SOS writes an alert to Firebase and sends an SMS to a registered emergency contact

For Transport Offices (यातायात कार्यालय)

  • Fleet dashboard — enter a number plate or driver ID, see the bus live on a map
  • Driver reputation lookup — view any driver's on-chain score, trip count, ZK verification status
  • Real-time analytics — trips tracked today, active buses, route coverage
  • Compliance monitoring — programmatic vehicle tracking without trusting operator self-reporting

Architecture

┌───────────────────────────────────────────────────────────┐
│                      CLIENT LAYER                         │
│                                                           │
│  Passenger App (/passenger)    Driver App (/driver)       │
│  • Leaflet map + OSRM route   • Cockpit dashboard        │
│  • 10km radius driver filter  • TripRequestPanel          │
│  • ETA card (Phase 1 + 2)     • Accept / Reject / Board  │
│  • Soulbound receipt viewer   • Passenger "P" marker      │
│  • Wallet connect (Phantom)   • SOS emergency button      │
└──────────────┬────────────────────────┬───────────────────┘
               │                        │
               ▼                        ▼
┌───────────────────────────────────────────────────────────┐
│                   FIREBASE REALTIME DB                     │
│                                                           │
│  buses/{id}               ← driver GPS every 5s          │
│  drivers/active/{id}      ← presence + heading + speed   │
│  trips/{tripId}           ← status state machine         │
│    .status: requested → accepted → arrived → active       │
│             → completed                                   │
│  tripLocations/{tripId}/  ← participant-only paths       │
│    driver/                ← driver position (5s)         │
│    passenger/             ← passenger position (3s,      │
│                              published only after accept) │
│  users/{uid}              ← profile + role               │
│  bookings/                ← seat reservation records     │
│  alerts/                  ← SOS / emergency events       │
└──────────────┬────────────────────────────────────────────┘
               │
               ▼
┌───────────────────────────────────────────────────────────┐
│                 SOLANA SETTLEMENT LAYER                    │
│                                                           │
│  Token-2022 Soulbound NFT    ← minted per trip           │
│    NonTransferable extension ← cannot be moved            │
│    MetadataPointer extension ← trip data embedded         │
│                                                           │
│  DriverReputation PDA        ← on-chain driver score     │
│    seeds: ["driver_rep", driver_pubkey]                   │
│    fields: total_trips, avg_rating, zk_verified,          │
│            on_time_rate, sos_count                        │
│                                                           │
│  PassengerReputation PDA     ← on-chain passenger tier   │
│    seeds: ["passenger_rep", passenger_pubkey]             │
│    fields: total_rides, no_shows, loyalty_tier            │
│                                                           │
│  TripRecord PDA              ← immutable per-trip record │
│    seeds: ["trip", driver_pubkey, trip_id]                │
│                                                           │
│  EscrowAccount PDA           ← GPS-verified fare release │
│    seeds: ["escrow", trip_id]                             │
│                                                           │
│  ZK Commitment               ← Poseidon hash via Memo   │
└──────────────┬────────────────────────────────────────────┘
               │
               ▼
┌───────────────────────────────────────────────────────────┐
│                   ROUTING LAYER (OSRM)                    │
│                                                           │
│  Phase 1: driver → pickup pin ETA (30s refresh)          │
│  Phase 2: driver → destination ETA (after boarding)      │
│  GeoJSON LineString polyline rendered on Leaflet map      │
└───────────────────────────────────────────────────────────┘

Trip Status State Machine

idle ──► requested ──► accepted ──► arrived ──► active ──► completed
              │                                              │
              ├──► rejected                                  └──► NFT minted
              ├──► cancelled                                      SMS sent
              └──► expired (5-min passenger / 90-sec driver)      Reputation updated

Visibility and Privacy Model

State Passenger sees Driver sees Location data
idle Anonymous driver pins within 10km Nothing Passenger GPS local only
requested Selected driver moving Pickup pin from trip record Passenger NOT published
accepted Driver live + ETA card Passenger "P" marker live Both publish to tripLocations/
arrived "Driver has arrived" alert "Passenger reached" alert Both published
active ETA to destination + polyline Passenger location live Both published
completed Receipt NFT in wallet Ready for next request Publishing stops, path cleaned

Firebase Security Rules

Path Read Write
buses/ All authenticated Driver's own record only
drivers/active/ All authenticated Driver's own record only
trips/{id} Participant only Any authenticated (creation)
tripLocations/{id}/driver Participant only Driver only
tripLocations/{id}/passenger Participant only Passenger only
locations/{uid} Owner only Owner only
users/{uid} Any authenticated Owner only

TRRL — Tokenized Ride-Sharing Reputation Layer

TRRL is the protocol layer that transforms Yatra from a transit app into infrastructure. It is a permissionless on-chain reputation system for ride-sharing drivers and passengers.

Driver Reputation Score (0–1000)

base  = (completed_trips / total_trips) × 400        // Completion rate
      + (avg_rating / 5.0) × 300                      // Rating weight
      + min(on_time_arrivals / completed_trips, 1) × 200  // Punctuality
      + (zk_verified ? 100 : 0)                        // Identity bonus
      - (sos_triggered × 20)                           // Safety penalty
      = capped at 1000

Cross-Platform Integration

Third-party integrations can query a driver's reputation through the typed SDK layer:

import { YatraProtocol } from '@/lib/sdk';

const rep = await new YatraProtocol().getDriverReputation(driverWallet);
// {
//   totalRides: 847,
//   averageRating: 4.85,
//   isZkVerified: true,
//   onTimeRate: 0.93,
//   loyaltyTier: 'gold',
//   score: 892
// }

No API key. No permission. No agreement with Yatra. The data is on Solana — it is public, permissionless, and composable.

Why This Matters

A driver in Butwal spends 5 years building a perfect rating. The operator closes. On every existing platform, that driver starts at zero. With TRRL, that driver's 1,247-trip history is on-chain. Any new platform reads it in 2 seconds. The driver's reputation is finally, for the first time, theirs.


ZK Identity System

Yatra uses a Groth16 zero-knowledge circuit to verify driver identity without exposing raw credentials.

Input: [licenseNumber, birthYear]
         │
         ▼
  ┌──────────────────┐
  │  Poseidon Hash   │ ← commitment = H(license, birthYear)
  └────────┬─────────┘
           ▼
  ┌──────────────────┐
  │  Age Constraint  │ ← GreaterEqThan(18): birthYear ≤ currentYear - 18
  └────────┬─────────┘
           ▼
  ┌──────────────────┐
  │  Groth16 Proof   │ ← generated client-side via SnarkJS
  └────────┬─────────┘
           ▼
  Server: snarkjs.groth16.verify(vk, publicSignals, proof)
           │
           ▼
  On-chain: commitment anchored via Solana Memo tx
            DriverReputation PDA: zk_verified = true

The driver's license number and birth year never leave their device. Only the cryptographic proof and the Poseidon commitment are transmitted. The server verifies the math without seeing the inputs.


Fare Escrow (GPS-Verified)

Passenger books trip
    │
    ▼
Fare locked in EscrowAccount PDA (devnet USDC)
    │
    ├── Driver completes trip
    │   │
    │   ▼
    │   GPS confirms drop-off within 200m of destination
    │   │
    │   ▼
    │   Escrow releases to driver's USDC ATA
    │
    └── 2-hour timeout with no completion
        │
        ▼
        Passenger reclaims escrow

Getting Started

Prerequisites

Tool Version Purpose
Node.js 18+ Runtime
npm 9+ Package manager
Solana CLI 1.18+ Keypair generation (optional)
Firebase project Realtime Database + Authentication enabled

Installation

git clone https://github.com/AATechCulworx/yatra.git
cd yatra
npm install

Environment Variables

Create .env.local in the project root:

# ── Solana ──────────────────────────────────────────
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_KEYPAIR=[your_base58_or_array_private_key]

# ── Firebase Client ──────────────────────────────────
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_DATABASE_URL=https://your_project-default-rtdb.europe-west1.firebasedatabase.app
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id

# ── Firebase Admin SDK (server-side) ────────────────
FIREBASE_PROJECT_ID=your_project_id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@your_project.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
FIREBASE_DATABASE_URL=https://your_project-default-rtdb.europe-west1.firebasedatabase.app

# ── SMS (optional, for real notifications) ──────────
SPARROWSMS_TOKEN=your_sparrowsms_token

Security: Never commit .env.local to git. The .gitignore already excludes it.

Run

npm run dev        # Development server → http://localhost:3000
npm run build      # Production build
npm run start      # Production server
npm run lint       # ESLint
npx tsc --noEmit   # Type check without emitting

Project Structure

yatra/
├── app/
│   ├── api/
│   │   ├── auth/             # Session login/logout, register, verify-driver
│   │   ├── bookings/         # Create, calculate-fare, booking lifecycle
│   │   ├── buses/            # Bus CRUD and state management
│   │   ├── trip-requests/    # Trip request creation + FCM notification
│   │   ├── solana/           # NFT minting, driver badge, trip completion
│   │   └── seed/             # Test data seeder (dev only)
│   ├── auth/                 # Login, signup, profile setup
│   ├── driver/               # Driver cockpit dashboard
│   ├── passenger/            # Passenger map + booking UI
│   ├── admin/                # Admin panel
│   └── page.tsx              # 3D immersive landing page
│
├── components/
│   ├── landing/              # Three.js 3D scene, scroll animations, navbar
│   ├── driver/               # TripRequestPanel, cockpit controls
│   ├── passenger/            # Booking UI, ETA cards, receipt viewer
│   ├── map/                  # Leaflet map, markers, route polyline
│   ├── onboarding/           # Role selection wizard
│   ├── ui/                   # shadcn/ui primitives (Radix-based)
│   └── shared/               # Common elements
│
├── lib/
│   ├── solana/
│   │   ├── connection.ts     # Solana RPC connection
│   │   ├── tripTicket.ts     # Token-2022 Soulbound NFT minting
│   │   ├── tokenExtensions.ts # Token-2022 extension helpers
│   │   ├── trrl.ts           # TRRL reputation SDK
│   │   └── escrow.ts         # Fare escrow operations
│   ├── zk/
│   │   ├── prover.ts         # Client-side Groth16 proof generation
│   │   └── verifier.ts       # Server-side snarkjs.groth16.verify()
│   ├── routing/
│   │   └── osrm.ts           # OSRM route + ETA fetching
│   ├── contexts/
│   │   └── AuthContext.tsx    # Firebase auth state + profile subscription
│   ├── utils/
│   │   ├── fareCalculator.ts # Distance-based fare calculation
│   │   ├── etaCalculator.ts  # ETA estimation
│   │   ├── geofencing.ts     # Haversine distance + radius checks
│   │   └── cn.ts             # clsx + tailwind-merge
│   ├── firebase.ts           # Client-side Firebase singleton
│   ├── firebaseAdmin.ts      # Server-side Admin SDK singleton
│   ├── firebaseDb.ts         # All RTDB operations
│   ├── types.ts              # Shared types + TripStatus + RequestStatus
│   └── constants.ts          # Vehicle types, defaults
│
├── hooks/
│   ├── useLiveLocation.ts    # GPS watch + Firebase publish
│   ├── useAccidentDetection.ts # Sudden deceleration detection
│   └── useProximityHandshake.ts # Geofenced proximity alerts
│
├── circuits/
│   └── driverIdentity.circom # Groth16 ZK circuit (Poseidon + age check)
│
├── middleware.ts              # Cookie-based route guards
├── database.rules.json        # Firebase security rules
└── package.json

Tech Stack

Layer Technology Why
Framework Next.js 16 (App Router), React 19 Server components, API routes, edge middleware
Language TypeScript 5 Type safety across client + server + blockchain
3D / Landing Three.js, @react-three/fiber, @react-three/drei, GSAP Immersive 3D landing page with scroll-synced animation
Smooth Scroll Lenis Buttery scroll physics for the landing experience
Blockchain Solana Web3.js, SPL Token-2022 Soulbound NFTs, reputation PDAs, fare escrow
ZK Identity SnarkJS (Groth16), Circom Client-side proof generation, server-side verification
Database Firebase Realtime DB + Admin SDK Sub-second GPS sync, presence detection, onDisconnect
Maps Leaflet.js + React-Leaflet Lightweight, mobile-friendly map rendering
Routing OSRM (Open Source Routing Machine) Turn-by-turn ETA and GeoJSON route polylines
Auth Firebase Authentication Phone OTP, email/password, Google OAuth
Forms React Hook Form + Zod Validated, performant form handling
UI Tailwind CSS v4, shadcn/ui, Framer Motion Utility-first styling, accessible primitives, smooth animation
Notifications Firebase Cloud Messaging + SparrowSMS Push notifications + Nepal SMS delivery

Business Model

Stream Model Scale
Booking fee 1% of every fare ~$100k ARR at 5% market penetration
Fleet subscription NPR 500/bus/month for transport operators Recurring B2B revenue
Protocol API fee $0.001 per TRRL reputation query Passive protocol revenue at scale

Roadmap

  • Firebase auth with phone OTP, email, and Google OAuth
  • Real-time GPS tracking with sub-3-second latency
  • Booking lifecycle with seat management
  • ZK prover (client-side Groth16 proof generation)
  • Token-2022 Soulbound NFT minting (devnet)
  • Proximity alerts (haversine geofencing)
  • OSRM integration for ETA and routing
  • 3D immersive landing page (Three.js + scroll animation)
  • Trip request + FCM push notification to driver
  • Driver accept/reject panel with 90-second countdown
  • Two-phase ETA (pickup + destination) with route polyline
  • Participant-only visibility (tripLocations path)
  • Passenger wallet connect (Phantom) + NFT receipt delivery
  • DriverReputation tracking via TRRL integration
  • Passenger loyalty tiers (Bronze/Silver/Gold)
  • ZK verifier wired to snarkjs.groth16.verify()
  • Fare escrow with GPS-verified release
  • Transport office dashboard (Live map & Analytics)
  • Driver Reputation Lookup UI for Transport Office
  • Typed SDK query layer (lib/sdk) for third-party integration
  • SparrowSMS integration for real notifications
  • Mainnet deployment

Contributing

Yatra is open source. Contributions are welcome.

# Fork the repo, create a branch, make changes, then:
npm run lint          # Must pass
npx tsc --noEmit      # Must pass
npm run build         # Must succeed
# Then open a PR

Acknowledgments


License

MIT — see LICENSE for details.



Built in Butwal, Nepal 🇳🇵by Team Aparicchit

Powered by Solana ◎


Every journey, verified. Every driver, accountable. Every rupee, traceable.


yatra-chi.vercel.app

About

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 93.6%
  • JavaScript 3.8%
  • CSS 2.5%
  • Circom 0.1%