Source Code

;; Reputation System Contract
;; On-chain reputation and reviews

(define-constant contract-owner tx-sender)
(define-constant err-already-reviewed (err u100))
(define-constant err-self-review (err u101))
(define-constant err-invalid-rating (err u102))

(define-map reputation
    principal
    {
        total-score: uint,
        review-count: uint,
        positive-reviews: uint,
        negative-reviews: uint
    }
)

(define-map reviews
    {reviewer: principal, reviewee: principal}
    {
        rating: uint,
        comment: (string-utf8 500),
        timestamp: uint
    }
)

;; Submit a review
(define-public (submit-review (reviewee principal) (rating uint) (comment (string-utf8 500)))
    (let
        (
            (review-key {reviewer: tx-sender, reviewee: reviewee})
            (current-rep (default-to 
                {total-score: u0, review-count: u0, positive-reviews: u0, negative-reviews: u0}
                (map-get? reputation reviewee)))
        )
        (asserts! (not (is-eq tx-sender reviewee)) err-self-review)
        (asserts! (and (>= rating u1) (<= rating u5)) err-invalid-rating)
        (asserts! (is-none (map-get? reviews review-key)) err-already-reviewed)
        
        (map-set reviews review-key {
            rating: rating,
            comment: comment,
            timestamp: block-height
        })
        
        (map-set reputation reviewee {
            total-score: (+ (get total-score current-rep) rating),
            review-count: (+ (get review-count current-rep) u1),
            positive-reviews: (if (>= rating u4) 
                                  (+ (get positive-reviews current-rep) u1)
                                  (get positive-reviews current-rep)),
            negative-reviews: (if (<= rating u2)
                                  (+ (get negative-reviews current-rep) u1)
                                  (get negative-reviews current-rep))
        })
        
        (ok true)
    )
)

;; Update existing review
(define-public (update-review (reviewee principal) (new-rating uint) (new-comment (string-utf8 500)))
    (let
        (
            (review-key {reviewer: tx-sender, reviewee: reviewee})
            (old-review (unwrap! (map-get? reviews review-key) err-already-reviewed))
            (current-rep (unwrap! (map-get? reputation reviewee) err-already-reviewed))
            (old-rating (get rating old-review))
        )
        (asserts! (and (>= new-rating u1) (<= new-rating u5)) err-invalid-rating)
        
        (map-set reviews review-key {
            rating: new-rating,
            comment: new-comment,
            timestamp: block-height
        })
        
        ;; Adjust reputation scores
        (map-set reputation reviewee {
            total-score: (+ (- (get total-score current-rep) old-rating) new-rating),
            review-count: (get review-count current-rep),
            positive-reviews: (+ (- (get positive-reviews current-rep) 
                                   (if (>= old-rating u4) u1 u0))
                                (if (>= new-rating u4) u1 u0)),
            negative-reviews: (+ (- (get negative-reviews current-rep)
                                   (if (<= old-rating u2) u1 u0))
                                (if (<= new-rating u2) u1 u0))
        })
        
        (ok true)
    )
)

;; Get average rating
(define-read-only (get-average-rating (user principal))
    (match (map-get? reputation user)
        rep (if (> (get review-count rep) u0)
                (some (/ (* (get total-score rep) u100) (get review-count rep)))
                none)
        none
    )
)

;; Get reputation
(define-read-only (get-reputation (user principal))
    (map-get? reputation user)
)

;; Get specific review
(define-read-only (get-review (reviewer principal) (reviewee principal))
    (map-get? reviews {reviewer: reviewer, reviewee: reviewee})
)

;; Calculate reputation score (0-100)
(define-read-only (get-reputation-score (user principal))
    (match (map-get? reputation user)
        rep (let
                (
                    (avg-rating (/ (* (get total-score rep) u100) 
                                  (if (> (get review-count rep) u0) 
                                      (get review-count rep) 
                                      u1)))
                    (positive-ratio (if (> (get review-count rep) u0)
                                       (/ (* (get positive-reviews rep) u100) (get review-count rep))
                                       u0))
                )
                (* (/ (+ avg-rating positive-ratio) u2) u2)
            )
        u0
    )
)

Functions (6)

FunctionAccessArgs
submit-reviewpublicreviewee: principal, rating: uint, comment: (string-utf8 500
update-reviewpublicreviewee: principal, new-rating: uint, new-comment: (string-utf8 500
get-average-ratingread-onlyuser: principal
get-reputationread-onlyuser: principal
get-reviewread-onlyreviewer: principal, reviewee: principal
get-reputation-scoreread-onlyuser: principal