Source Code

;; Quran Certificate Contract
;; Quran memorization milestone certificates
;; Halal - encouraging Quran learning
;; Clarity 4 compatible

(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-NOT-AUTHORIZED (err u401))
(define-constant ERR-NOT-FOUND (err u404))
(define-constant ERR-NOT-TEACHER (err u405))

(define-data-var cert-count uint u0)
(define-data-var student-count uint u0)

(define-map teachers principal { name: (string-utf8 100), institution: (string-utf8 100), certs-issued: uint, verified: bool })
(define-map students-reg principal { name: (string-utf8 100), teacher: principal, juz-completed: uint, enrolled: uint })
(define-map certificates uint {
  student: principal, teacher: principal, milestone: (string-utf8 100),
  juz-from: uint, juz-to: uint, grade: (string-ascii 10),
  cert-hash: (buff 32), issued: uint
})
(define-map student-certs { student: principal, index: uint } uint)
(define-map student-cert-count principal uint)

(define-public (register-teacher (name (string-utf8 100)) (institution (string-utf8 100)))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-set teachers tx-sender { name: name, institution: institution, certs-issued: u0, verified: true }) (ok true)))

(define-public (add-teacher (teacher principal) (name (string-utf8 100)) (institution (string-utf8 100)))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-NOT-AUTHORIZED)
    (map-set teachers teacher { name: name, institution: institution, certs-issued: u0, verified: true }) (ok true)))

(define-public (enroll-student (name (string-utf8 100)))
  (begin
    (map-set students-reg tx-sender { name: name, teacher: CONTRACT-OWNER, juz-completed: u0, enrolled: stacks-block-height })
    (var-set student-count (+ (var-get student-count) u1)) (ok true)))

(define-public (issue-certificate (student principal) (milestone (string-utf8 100)) (juz-from uint) (juz-to uint) (grade (string-ascii 10)) (cert-hash (buff 32)))
  (let (
    (teacher (unwrap! (map-get? teachers tx-sender) ERR-NOT-TEACHER))
    (id (+ (var-get cert-count) u1))
    (sc (default-to u0 (map-get? student-cert-count student)))
  )
    (asserts! (get verified teacher) ERR-NOT-TEACHER)
    (map-set certificates id { student: student, teacher: tx-sender, milestone: milestone, juz-from: juz-from, juz-to: juz-to, grade: grade, cert-hash: cert-hash, issued: stacks-block-height })
    (map-set student-certs { student: student, index: sc } id)
    (map-set student-cert-count student (+ sc u1))
    (map-set teachers tx-sender (merge teacher { certs-issued: (+ (get certs-issued teacher) u1) }))
    (match (map-get? students-reg student)
      s (map-set students-reg student (merge s { juz-completed: juz-to })) true)
    (var-set cert-count id) (ok id)))

(define-read-only (get-certificate (id uint)) (map-get? certificates id))
(define-read-only (get-teacher (who principal)) (map-get? teachers who))
(define-read-only (get-student (who principal)) (map-get? students-reg who))
(define-read-only (get-student-cert (student principal) (index uint)) (map-get? student-certs { student: student, index: index }))
(define-read-only (get-cert-count) (ok (var-get cert-count)))
(define-read-only (get-student-count) (ok (var-get student-count)))

Functions (10)

FunctionAccessArgs
register-teacherpublicname: (string-utf8 100
add-teacherpublicteacher: principal, name: (string-utf8 100
enroll-studentpublicname: (string-utf8 100
issue-certificatepublicstudent: principal, milestone: (string-utf8 100
get-certificateread-onlyid: uint
get-teacherread-onlywho: principal
get-studentread-onlywho: principal
get-student-certread-onlystudent: principal, index: uint
get-cert-countread-only
get-student-countread-only