Source Code

;; title: quest-registry
;; summary: Stores quest definitions and rewards for use by quest-progress
;; version: 1

;; constants
(define-constant err-not-owner (err u100))
(define-constant err-name-required (err u101))
(define-constant err-quest-not-found (err u102))
(define-constant err-type-inactive (err u103))
(define-constant err-type-missing (err u104))
(define-constant err-uri-required (err u105))

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

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

;; data maps
;; { id } -> { name, type-id, xp-reward, badge-uri, active }
(define-map quests
  { id: uint }
  {
    name: (string-utf8 64),
    type-id: uint,
    xp-reward: uint,
    badge-uri: (string-utf8 256),
    active: bool
  })

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

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

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

;; public functions

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

;; admin: create a quest definition
(define-public (create-quest (name (string-utf8 64)) (type-id uint) (xp-reward uint) (badge-uri (string-utf8 256)))
  (begin
    (asserts! (is-owner tx-sender) err-not-owner)
    (asserts! (> (len name) u0) err-name-required)
    (asserts! (> (len badge-uri) u0) err-uri-required)
    (let ((type-entry (unwrap! (contract-call? .quest-types-v2 get-type type-id) err-type-missing)))
      (asserts! (get active type-entry) err-type-inactive))
    (let ((id (var-get next-quest-id)))
      (map-set quests { id: id }
        { name: name, type-id: type-id, xp-reward: xp-reward, badge-uri: badge-uri, active: true })
      (var-set next-quest-id (+ id u1))
      (print { event: "create-quest", id: id, type: type-id, xp: xp-reward })
      (ok id))))

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

;; admin: update XP reward
(define-public (set-quest-xp (id uint) (xp-reward uint))
  (begin
    (asserts! (is-owner tx-sender) err-not-owner)
    (asserts! (quest-exists? id) err-quest-not-found)
    (let ((entry (unwrap! (fetch-quest-or-err id) err-quest-not-found)))
      (map-set quests { id: id }
        {
          name: (get name entry),
          type-id: (get type-id entry),
          xp-reward: xp-reward,
          badge-uri: (get badge-uri entry),
          active: (get active entry)
        }))
    (print { event: "set-quest-xp", id: id, xp: xp-reward })
    (ok xp-reward)))

;; admin: update badge URI
(define-public (set-quest-badge-uri (id uint) (badge-uri (string-utf8 256)))
  (begin
    (asserts! (is-owner tx-sender) err-not-owner)
    (asserts! (> (len badge-uri) u0) err-uri-required)
    (asserts! (quest-exists? id) err-quest-not-found)
    (let ((entry (unwrap! (fetch-quest-or-err id) err-quest-not-found)))
      (map-set quests { id: id }
        {
          name: (get name entry),
          type-id: (get type-id entry),
          xp-reward: (get xp-reward entry),
          badge-uri: badge-uri,
          active: (get active entry)
        }))
    (print { event: "set-quest-badge-uri", id: id })
    (ok true)))

;; read only functions

(define-read-only (get-quest (id uint))
  (fetch-quest-or-err id))

(define-read-only (quest-is-active (id uint))
  (match (fetch-quest-or-err id)
    entry (ok (get active entry))
    err err-quest-not-found))

(define-read-only (get-next-quest-id)
  (ok (var-get next-quest-id)))

Functions (11)

FunctionAccessArgs
is-ownerprivatewho: principal
quest-exists?privateid: uint
fetch-quest-or-errprivateid: uint
set-adminpublicnew-admin: principal
create-questpublicname: (string-utf8 64
set-quest-activepublicid: uint, flag: bool
set-quest-xppublicid: uint, xp-reward: uint
set-quest-badge-uripublicid: uint, badge-uri: (string-utf8 256
get-questread-onlyid: uint
quest-is-activeread-onlyid: uint
get-next-quest-idread-only