Source Code

;; title: quest-types
;; summary: Registry of quest categories with simple admin controls
;; version: 1

(impl-trait .quest-types-trait-v2.quest-types-trait)

;; constants
(define-constant err-not-owner (err u100))
(define-constant err-name-required (err u101))
(define-constant err-type-not-found (err u102))

;; data vars
(define-data-var contract-admin principal tx-sender)
(define-data-var next-type-id uint u1)

;; data maps
;; id -> { name, description, active }
(define-map quest-types
  { id: uint }
  {
    name: (string-utf8 64),
    description: (optional (string-utf8 256)),
    active: bool
  })

;; private helpers
(define-private (is-owner (who principal))
  (is-eq who (var-get contract-admin)))

(define-private (assert-owner (who principal))
  (is-owner who))

(define-private (type-exists? (id uint))
  (is-some (map-get? quest-types { id: id })))

(define-private (fetch-type-or-err (id uint))
  (match (map-get? quest-types { id: id })
    entry (ok entry)
    err-type-not-found))

;; public functions

;; admin: set a new contract admin
(define-public (set-admin (new-admin principal))
  (begin
    (asserts! (assert-owner tx-sender) err-not-owner)
    (var-set contract-admin new-admin)
    (print { event: "set-admin", admin: new-admin })
    (ok true)))

;; admin: create a new quest type
(define-public (create-type (name (string-utf8 64)) (description (optional (string-utf8 256))))
  (begin
    (asserts! (assert-owner tx-sender) err-not-owner)
    (asserts! (> (len name) u0) err-name-required)
    (let ((id (var-get next-type-id)))
      (map-set quest-types { id: id } { name: name, description: description, active: true })
      (var-set next-type-id (+ id u1))
      (print { event: "create-type", id: id, name: name })
      (ok id))))

;; admin: toggle type active flag
(define-public (set-type-active (id uint) (flag bool))
  (begin
    (asserts! (assert-owner tx-sender) err-not-owner)
    (asserts! (type-exists? id) err-type-not-found)
    (let ((entry (unwrap! (fetch-type-or-err id) err-type-not-found)))
      (map-set quest-types { id: id }
        {
          name: (get name entry),
          description: (get description entry),
          active: flag
        }))
    (print { event: "set-type-active", id: id, active: flag })
    (ok flag)))

;; read only functions

;; get a type by id
(define-read-only (get-type (id uint))
  (fetch-type-or-err id))

;; check if a type is active
(define-read-only (is-type-active (id uint))
  (match (fetch-type-or-err id)
    entry (ok (get active entry))
    err err-type-not-found))

;; get the next type id that will be assigned
(define-read-only (get-next-type-id)
  (ok (var-get next-type-id)))

Functions (10)

FunctionAccessArgs
is-ownerprivatewho: principal
assert-ownerprivatewho: principal
type-exists?privateid: uint
fetch-type-or-errprivateid: uint
set-adminpublicnew-admin: principal
create-typepublicname: (string-utf8 64
set-type-activepublicid: uint, flag: bool
get-typeread-onlyid: uint
is-type-activeread-onlyid: uint
get-next-type-idread-only