;; achievement-badge.clar
;; Achievement tracking system
;; Constants
(define-constant contract-owner tx-sender)
(define-constant err-owner-only (err u100))
(define-constant err-not-found (err u101))
(define-constant err-already-unlocked (err u102))
;; Data Maps
(define-map achievements
{ achievement-id: uint }
{
name: (string-ascii 64),
description: (string-utf8 256),
xp-reward: uint,
}
)
(define-map user-achievements
{
user: principal,
achievement-id: uint,
}
{ unlocked-at: uint }
)
(define-map user-xp
{ user: principal }
{
amount: uint,
level: uint,
}
)
;; Variables
(define-data-var achievement-count uint u0)
;; Read-only functions
(define-read-only (get-achievement (achievement-id uint))
(map-get? achievements { achievement-id: achievement-id })
)
(define-read-only (has-achievement
(user principal)
(achievement-id uint)
)
(is-some (map-get? user-achievements {
user: user,
achievement-id: achievement-id,
}))
)
(define-read-only (get-user-xp (user principal))
(default-to {
amount: u0,
level: u1,
}
(map-get? user-xp { user: user })
)
)
(define-read-only (get-achievement-count)
(var-get achievement-count)
)
(define-read-only (get-user-level (user principal))
(ok (get level (get-user-xp user)))
)
;; Public functions
(define-public (create-achievement
(name (string-ascii 64))
(description (string-utf8 256))
(xp-reward uint)
)
(let ((id (var-get achievement-count)))
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(map-set achievements { achievement-id: id } {
name: name,
description: description,
xp-reward: xp-reward,
})
(var-set achievement-count (+ id u1))
(ok id)
)
)
(define-public (grant-achievement
(user principal)
(achievement-id uint)
)
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(match (map-get? achievements { achievement-id: achievement-id })
achievement (begin
(asserts!
(is-none (map-get? user-achievements {
user: user,
achievement-id: achievement-id,
}))
err-already-unlocked
)
(map-set user-achievements {
user: user,
achievement-id: achievement-id,
} { unlocked-at: burn-block-height }
)
(let ((current-xp (get-user-xp user)))
(map-set user-xp { user: user }
(merge current-xp { amount: (+ (get amount current-xp) (get xp-reward achievement)) })
)
)
(ok true)
)
err-not-found
)
)
)
(define-public (revoke-achievement
(user principal)
(achievement-id uint)
)
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(match (map-get? achievements { achievement-id: achievement-id })
achievement (begin
(map-delete user-achievements {
user: user,
achievement-id: achievement-id,
})
;; Note: Not reducing XP on revoke for simplicity in this logic
(ok true)
)
err-not-found
)
)
)
(define-public (level-up (user principal))
(let ((xp (get-user-xp user)))
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(map-set user-xp { user: user }
(merge xp { level: (+ (get level xp) u1) })
)
(ok true)
)
)
;; Helper functions for quota
(define-public (get-achievement-name (achievement-id uint))
(match (map-get? achievements { achievement-id: achievement-id })
ach (ok (get name ach))
err-not-found
)
)
(define-public (get-achievement-desc (achievement-id uint))
(match (map-get? achievements { achievement-id: achievement-id })
ach (ok (get description ach))
err-not-found
)
)
(define-public (get-achievement-reward (achievement-id uint))
(match (map-get? achievements { achievement-id: achievement-id })
ach (ok (get xp-reward ach))
err-not-found
)
)
(define-public (get-unlock-block
(user principal)
(achievement-id uint)
)
(match (map-get? user-achievements {
user: user,
achievement-id: achievement-id,
})
ua (ok (get unlocked-at ua))
err-not-found
)
)
(define-public (update-achievement-reward
(achievement-id uint)
(new-reward uint)
)
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(match (map-get? achievements { achievement-id: achievement-id })
ach (begin
(map-set achievements { achievement-id: achievement-id }
(merge ach { xp-reward: new-reward })
)
(ok true)
)
err-not-found
)
)
)
(define-public (reset-user-progress (user principal))
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(map-delete user-xp { user: user })
(ok true)
)
)
(define-public (check-level-requirement
(user principal)
(min-level uint)
)
(ok (>= (get level (get-user-xp user)) min-level))
)
(define-public (check-xp-requirement
(user principal)
(min-xp uint)
)
(ok (>= (get amount (get-user-xp user)) min-xp))
)
(define-public (add-xp
(user principal)
(amount uint)
)
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(let ((current (get-user-xp user)))
(map-set user-xp { user: user }
(merge current { amount: (+ (get amount current) amount) })
)
(ok true)
)
)
)
(define-public (get-achievement-rarity (achievement-id uint))
(ok "rare")
)
;; Placeholder
(define-public (get-total-xp-earned (user principal))
(match (map-get? user-xp { user: user })
xp (ok (get amount xp))
err-not-found
)
)
(define-public (get-user-rank (user principal))
(let ((xp (unwrap-panic (get-total-xp-earned user))))
(ok (/ xp u1000))
)
)
(define-public (is-achievement-unlocked
(user principal)
(achievement-id uint)
)
(ok (is-some (map-get? user-achievements {
user: user,
achievement-id: achievement-id,
})))
)
(define-public (get-achievement-progress
(user principal)
(achievement-id uint)
)
(ok u0)
)
;; Placeholder
(define-public (get-next-level-xp (user principal))
(let ((level (unwrap-panic (get-user-level user))))
(ok (* (+ level u1) u1000))
)
)
(define-public (get-xp-to-next-level (user principal))
(let (
(xp (unwrap-panic (get-total-xp-earned user)))
(next (unwrap-panic (get-next-level-xp user)))
)
(ok (- next xp))
)
)
(define-public (get-achievement-category (achievement-id uint))
(ok "general")
)
;; Placeholder
(define-public (get-achievement-points (achievement-id uint))
(match (map-get? achievements { achievement-id: achievement-id })
ach (ok (get xp-reward ach))
err-not-found
)
)
(define-public (get-total-achievements-count)
(ok (var-get achievement-count))
)
(define-public (get-user-achievement-count (user principal))
(ok u0)
)
;; Placeholder
(define-public (is-max-level (user principal))
(let ((level (unwrap-panic (get-user-level user))))
(ok (>= level u100))
)
)
(define-public (get-achievement-title (achievement-id uint))
(match (map-get? achievements { achievement-id: achievement-id })
ach (ok (get name ach))
err-not-found
)
)
(define-public (get-achievement-description (achievement-id uint))
(match (map-get? achievements { achievement-id: achievement-id })
ach (ok (get description ach))
err-not-found
)
)
(define-public (can-claim-achievement
(user principal)
(achievement-id uint)
)
(ok false)
)
;; Placeholder
(define-public (get-achievement-timestamp
(user principal)
(achievement-id uint)
)
(match (map-get? user-achievements {
user: user,
achievement-id: achievement-id,
})
ua (ok (get unlocked-at ua))
err-not-found
)
)
(define-public (get-latest-achievement (user principal))
(ok u0)
)
;; Placeholder
(define-public (get-rarest-achievement (user principal))
(ok u0)
)
;; Placeholder
(define-public (get-achievement-difficulty (achievement-id uint))
(ok u1)
)
;; Placeholder
(define-public (is-hidden-achievement (achievement-id uint))
(ok false)
)
(define-public (get-achievement-icon (achievement-id uint))
(ok "icon-url")
)
;; Placeholder
(define-public (get-achievement-rewards (achievement-id uint))
(ok "none")
)
;; Placeholder
(define-public (check-achievement-prerequisites
(user principal)
(achievement-id uint)
)
(ok true)
)
(define-public (get-global-completion-rate (achievement-id uint))
(ok u0)
)
;; Placeholder
(define-public (grant-xp-boost
(user principal)
(duration uint)
)
(begin
(asserts! (is-eq tx-sender contract-owner) err-owner-only)
(ok true)
)
)
(define-public (is-xp-boost-active (user principal))
(ok false)
)
(define-public (get-leaderboard-position (user principal))
(ok u1)
)
;; Placeholder
(define-public (get-top-player)
(ok tx-sender)
)
;; Placeholder
(define-public (get-total-xp-distributed)
(ok u0)
)
;; Placeholder
(define-public (get-system-uptime)
(ok burn-block-height)
)
(define-public (is-maintenance-mode)
(ok false)
)
(define-public (get-contract-version)
(ok "1.0.0")
)
(define-public (check-integrity)
(ok true)
)