Source Code

(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-unauthorized (err u102))
(define-constant err-invalid-amount (err u104))
(define-constant err-driver-busy (err u129))

(define-data-var ride-nonce uint u0)

(define-map rides
  uint
  {
    rider: principal,
    driver: principal,
    pickup-location: (buff 32),
    dropoff-location: (buff 32),
    fare: uint,
    distance: uint,
    status: (string-ascii 20),
    requested-block: uint,
    completed-block: uint
  }
)

(define-map drivers
  principal
  {
    active: bool,
    total-rides: uint,
    earnings: uint,
    rating: uint,
    location-hash: (buff 32),
    vehicle-type: (string-ascii 20),
    available: bool
  }
)

(define-map riders
  principal
  {
    total-rides: uint,
    total-spent: uint,
    rating: uint
  }
)

(define-map driver-rides principal (list 500 uint))
(define-map rider-rides principal (list 200 uint))

(define-public (register-driver (vehicle-type (string-ascii 20)) (location (buff 32)))
  (begin
    (map-set drivers tx-sender {
      active: true,
      total-rides: u0,
      earnings: u0,
      rating: u100,
      location-hash: location,
      vehicle-type: vehicle-type,
      available: true
    })
    (ok true)
  )
)

(define-public (request-ride (pickup (buff 32)) (dropoff (buff 32)) (fare uint) (distance uint))
  (let
    (
      (ride-id (+ (var-get ride-nonce) u1))
    )
    (asserts! (> fare u0) err-invalid-amount)
    (map-set rides ride-id {
      rider: tx-sender,
      driver: tx-sender,
      pickup-location: pickup,
      dropoff-location: dropoff,
      fare: fare,
      distance: distance,
      status: "requested",
      requested-block: stacks-block-height,
      completed-block: u0
    })
    (let
      (
        (rider-data (default-to {total-rides: u0, total-spent: u0, rating: u100} 
                     (map-get? riders tx-sender)))
      )
      (map-set riders tx-sender rider-data)
    )
    (map-set rider-rides tx-sender
      (unwrap-panic (as-max-len? (append (default-to (list) (map-get? rider-rides tx-sender)) ride-id) u200)))
    (var-set ride-nonce ride-id)
    (ok ride-id)
  )
)

(define-public (accept-ride (ride-id uint))
  (let
    (
      (ride (unwrap! (map-get? rides ride-id) err-not-found))
      (driver-data (unwrap! (map-get? drivers tx-sender) err-not-found))
    )
    (asserts! (get available driver-data) err-driver-busy)
    (asserts! (is-eq (get status ride) "requested") err-unauthorized)
    (map-set rides ride-id (merge ride {driver: tx-sender, status: "accepted"}))
    (map-set drivers tx-sender (merge driver-data {available: false}))
    (map-set driver-rides tx-sender
      (unwrap-panic (as-max-len? (append (default-to (list) (map-get? driver-rides tx-sender)) ride-id) u500)))
    (ok true)
  )
)

(define-public (start-ride (ride-id uint))
  (let
    (
      (ride (unwrap! (map-get? rides ride-id) err-not-found))
    )
    (asserts! (is-eq tx-sender (get driver ride)) err-unauthorized)
    (asserts! (is-eq (get status ride) "accepted") err-unauthorized)
    (map-set rides ride-id (merge ride {status: "in-progress"}))
    (ok true)
  )
)

(define-public (complete-ride (ride-id uint))
  (let
    (
      (ride (unwrap! (map-get? rides ride-id) err-not-found))
      (driver-data (unwrap! (map-get? drivers tx-sender) err-not-found))
      (rider-data (unwrap! (map-get? riders (get rider ride)) err-not-found))
    )
    (asserts! (is-eq tx-sender (get driver ride)) err-unauthorized)
    (asserts! (is-eq (get status ride) "in-progress") err-unauthorized)
    (try! (stx-transfer? (get fare ride) (get rider ride) tx-sender))
    (map-set rides ride-id (merge ride {
      status: "completed",
      completed-block: stacks-block-height
    }))
    (map-set drivers tx-sender (merge driver-data {
      total-rides: (+ (get total-rides driver-data) u1),
      earnings: (+ (get earnings driver-data) (get fare ride)),
      available: true
    }))
    (map-set riders (get rider ride) (merge rider-data {
      total-rides: (+ (get total-rides rider-data) u1),
      total-spent: (+ (get total-spent rider-data) (get fare ride))
    }))
    (ok true)
  )
)

(define-public (cancel-ride (ride-id uint))
  (let
    (
      (ride (unwrap! (map-get? rides ride-id) err-not-found))
    )
    (asserts! (is-eq tx-sender (get rider ride)) err-unauthorized)
    (map-set rides ride-id (merge ride {status: "cancelled"}))
    (ok true)
  )
)

(define-read-only (get-ride (ride-id uint))
  (ok (map-get? rides ride-id))
)

(define-read-only (get-driver (driver principal))
  (ok (map-get? drivers driver))
)

(define-read-only (get-rider (rider principal))
  (ok (map-get? riders rider))
)

(define-read-only (get-driver-rides (driver principal))
  (ok (map-get? driver-rides driver))
)

(define-read-only (get-rider-rides (rider principal))
  (ok (map-get? rider-rides rider))
)

Functions (11)

FunctionAccessArgs
register-driverpublicvehicle-type: (string-ascii 20
request-ridepublicpickup: (buff 32
accept-ridepublicride-id: uint
start-ridepublicride-id: uint
complete-ridepublicride-id: uint
cancel-ridepublicride-id: uint
get-rideread-onlyride-id: uint
get-driverread-onlydriver: principal
get-riderread-onlyrider: principal
get-driver-ridesread-onlydriver: principal
get-rider-ridesread-onlyrider: principal